1use crate::parser::{self, ArgKind};
6
7#[derive(Debug)]
8pub struct Protocol {
9 pub name: String,
10 pub copyright: Option<String>,
11 pub description: Option<Description>,
12 pub interfaces: Vec<Interface>,
13}
14
15#[derive(Debug)]
16pub struct Description {
17 pub summary: String,
18 pub description: String,
19}
20
21#[derive(Debug)]
22pub struct Interface {
23 pub name: String,
24 pub version: u32,
25 pub description: Option<Description>,
26 pub requests: Vec<Message>,
27 pub events: Vec<Message>,
28 pub enums: Vec<Enum>,
29}
30
31#[derive(Debug)]
32pub struct Message {
33 pub name: String,
34 pub since: u32,
35 pub request_type: Option<String>,
36 pub description: Option<Description>,
37 pub args: Vec<Arg>,
38}
39
40#[derive(Debug)]
41pub struct Arg {
42 pub name: String,
43 pub kind: ArgKind,
44 pub summary: Option<String>,
45 pub interface: Option<String>,
46 pub nullable: bool,
47 pub enum_type: Option<String>,
48 pub description: Option<Description>,
49}
50
51#[derive(Debug)]
52pub struct Enum {
53 pub name: String,
54 pub since: u32,
55 pub bitfield: bool,
56 pub description: Option<Description>,
57 pub entries: Vec<EnumEntry>,
58}
59
60#[derive(Debug)]
61pub struct EnumEntry {
62 pub name: String,
63 pub value: i64,
64 pub summary: Option<String>,
65 pub since: u32,
66 pub description: Option<Description>,
67}
68
69pub type AstError = String;
70pub type AstResult<T> = Result<T, AstError>;
71
72fn build_protocol(node: parser::ParseNode) -> AstResult<Protocol> {
73 if let parser::ParseElement::Protocol { name } = node.element {
74 let mut copyright: Option<String> = None;
75 let mut description: Option<Description> = None;
76 let mut interfaces: Vec<Interface> = Vec::new();
77 for child in node.children {
78 match &child.element {
79 parser::ParseElement::Copyright => copyright = Some(build_copyright(child)?),
80 parser::ParseElement::Description { .. } => {
81 description = Some(build_description(child)?)
82 }
83 parser::ParseElement::Interface { .. } => interfaces.push(build_interface(child)?),
84 _ => return Err("Unsupported".to_owned()),
85 }
86 }
87 Ok(Protocol { name: name, copyright, description, interfaces })
88 } else {
89 Err("Unexpected Element; expected Protocol".to_owned())
90 }
91}
92
93fn build_copyright(node: parser::ParseNode) -> AstResult<String> {
94 if let Some(copyright) = node.body {
95 Ok(copyright)
96 } else {
97 Err(format!("Unexpected node {:?}", node))
98 }
99}
100
101fn build_description(node: parser::ParseNode) -> AstResult<Description> {
102 if let parser::ParseElement::Description { summary } = node.element {
103 Ok(Description { summary, description: node.body.unwrap_or_else(|| "".to_owned()) })
104 } else {
105 Err("Invalid node".to_owned())
106 }
107}
108
109fn build_interface(node: parser::ParseNode) -> AstResult<Interface> {
110 if let parser::ParseElement::Interface { name, version } = node.element {
111 let mut description: Option<Description> = None;
112 let mut requests: Vec<Message> = Vec::new();
113 let mut events: Vec<Message> = Vec::new();
114 let mut enums: Vec<Enum> = Vec::new();
115 for child in node.children {
116 match &child.element {
117 parser::ParseElement::Description { .. } => {
118 description = Some(build_description(child)?)
119 }
120 parser::ParseElement::Request { .. } => requests.push(build_request(child)?),
121 parser::ParseElement::Event { .. } => events.push(build_event(child)?),
122 parser::ParseElement::Enum { .. } => enums.push(build_enum(child)?),
123 _ => return Err("Unsupported".to_owned()),
124 }
125 }
126 Ok(Interface { name, version, description, requests, events, enums })
127 } else {
128 Err("Invalid node".to_owned())
129 }
130}
131
132fn build_request(node: parser::ParseNode) -> AstResult<Message> {
133 if let parser::ParseElement::Request { name, since, request_type } = node.element {
134 let mut description: Option<Description> = None;
135 let mut args: Vec<Arg> = Vec::new();
136 for child in node.children {
137 match &child.element {
138 parser::ParseElement::Description { .. } => {
139 description = Some(build_description(child)?)
140 }
141 parser::ParseElement::Arg { .. } => args.append(&mut build_arg(child)?),
142 _ => return Err("Unsupported".to_owned()),
143 }
144 }
145 Ok(Message { name, since, request_type, description, args })
146 } else {
147 Err("Invalid node".to_owned())
148 }
149}
150
151fn build_event(node: parser::ParseNode) -> AstResult<Message> {
152 if let parser::ParseElement::Event { name, since } = node.element {
153 let mut description: Option<Description> = None;
154 let mut args: Vec<Arg> = Vec::new();
155 for child in node.children {
156 match &child.element {
157 parser::ParseElement::Description { .. } => {
158 description = Some(build_description(child)?)
159 }
160 parser::ParseElement::Arg { .. } => args.append(&mut build_arg(child)?),
161 _ => return Err("Unsupported".to_owned()),
162 }
163 }
164 Ok(Message { name, since, description, args, request_type: None })
165 } else {
166 Err("Invalid node".to_owned())
167 }
168}
169
170fn build_arg(node: parser::ParseNode) -> AstResult<Vec<Arg>> {
171 if let parser::ParseElement::Arg { name, kind, summary, interface, nullable, enum_type } =
172 node.element
173 {
174 let mut description: Option<Description> = None;
175 for child in node.children {
176 match &child.element {
177 parser::ParseElement::Description { .. } => {
178 description = Some(build_description(child)?)
179 }
180 _ => return Err("Unsupported".to_owned()),
181 }
182 }
183 let arg = Arg { name, kind, summary, interface, nullable, enum_type, description };
184 if arg.kind == ArgKind::NewId && arg.interface.is_none() {
189 Ok(vec![
190 Arg {
191 name: format!("{}_interface_name", arg.name),
192 kind: ArgKind::String,
193 summary: None,
194 interface: None,
195 nullable: false,
196 enum_type: None,
197 description: None,
198 },
199 Arg {
200 name: format!("{}_interface_version", arg.name),
201 kind: ArgKind::Uint,
202 summary: None,
203 interface: None,
204 nullable: false,
205 enum_type: None,
206 description: None,
207 },
208 arg,
209 ])
210 } else {
211 Ok(vec![arg])
212 }
213 } else {
214 Err("Invalid node".to_owned())
215 }
216}
217
218fn build_enum(node: parser::ParseNode) -> AstResult<Enum> {
219 if let parser::ParseElement::Enum { name, since, bitfield } = node.element {
220 let mut description: Option<Description> = None;
221 let mut entries: Vec<EnumEntry> = Vec::new();
222 for child in node.children {
223 match &child.element {
224 parser::ParseElement::Description { .. } => {
225 description = Some(build_description(child)?)
226 }
227 parser::ParseElement::EnumEntry { .. } => entries.push(build_enum_entry(child)?),
228 _ => return Err("Unsupported".to_owned()),
229 }
230 }
231 Ok(Enum { name, since, bitfield, description, entries })
232 } else {
233 Err("Invalid node".to_owned())
234 }
235}
236
237fn build_enum_entry(node: parser::ParseNode) -> AstResult<EnumEntry> {
238 if let parser::ParseElement::EnumEntry { name, value, summary, since } = node.element {
239 let mut description: Option<Description> = None;
240 for child in node.children {
241 match &child.element {
242 parser::ParseElement::Description { .. } => {
243 description = Some(build_description(child)?)
244 }
245 _ => return Err("Unsupported".to_owned()),
246 }
247 }
248 Ok(EnumEntry { name, value, summary, since, description })
249 } else {
250 Err("Invalid node".to_owned())
251 }
252}
253
254impl Protocol {
255 pub fn from_parse_tree(parse_tree: parser::ParseNode) -> AstResult<Protocol> {
256 build_protocol(parse_tree)
257 }
258}