1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use std::{
4 convert::Infallible,
5 io::Read,
6 num::ParseIntError,
7 str::{FromStr, ParseBoolError},
8};
9use thiserror::Error;
10use xml::{
11 attribute::OwnedAttribute,
12 reader::{
13 EventReader,
14 ParserConfig,
15 XmlEvent::{self, *},
16 },
17};
18
19type Result<T> = std::result::Result<T, Error>;
20
21#[derive(Error, Debug)]
22pub enum Error {
23 #[error("no protocol in file")]
24 NoProtocol,
25 #[error("xml parsing failed")]
26 XmlParse(#[from] xml::reader::Error),
27 #[error("unexpected xml event: {0:?}")]
28 UnexpectedXmlEvent(XmlEvent),
29 #[error("unexpected xml element: {0}")]
30 UnexpectedXmlElement(String),
31 #[error("parsing int failed")]
32 ParseInt(#[from] ParseIntError),
33 #[error("parsing bool failed")]
34 ParseBool(#[from] ParseBoolError),
35 #[error("missing required attribute: {0}")]
36 MissingRequiredAttribute(String),
37 #[error("invalid argument kind: {0}")]
38 InvalidArgKind(String),
39}
40
41impl From<Infallible> for Error {
42 fn from(i: Infallible) -> Self {
43 match i {}
44 }
45}
46
47#[derive(Clone, Default, Debug, Eq, PartialEq)]
48#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49pub struct Protocol {
50 pub name: String,
51 pub copyright: String,
52 pub description: Option<Description>,
53 pub interfaces: Vec<Interface>,
54}
55
56#[derive(Clone, Default, Debug, Eq, PartialEq)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58pub struct Interface {
59 pub name: String,
60 pub version: u32,
61 pub description: Option<Description>,
62 pub requests: Vec<Request>,
63 pub events: Vec<Event>,
64 pub enums: Vec<Enum>,
65}
66
67#[derive(Clone, Default, Debug, Eq, PartialEq)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69pub struct Request {
70 pub name: String,
71 pub destructor: bool,
72 pub since: u32,
73 pub description: Option<Description>,
74 pub args: Vec<Arg>,
75}
76
77#[derive(Clone, Default, Debug, Eq, PartialEq)]
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
79pub struct Event {
80 pub name: String,
81 pub since: u32,
82 pub description: Option<Description>,
83 pub args: Vec<Arg>,
84}
85
86#[derive(Clone, Default, Debug, Eq, PartialEq)]
87#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
88pub struct Arg {
89 pub name: String,
90 pub kind: ArgKind,
91 pub summary: Option<String>,
92 pub interface: Option<String>,
93 pub allow_null: bool,
94 pub enumeration: Option<String>,
95 pub description: Option<Description>,
96}
97
98#[derive(Clone, Debug, Eq, PartialEq)]
99#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
100pub enum ArgKind {
101 NewId,
102 Int,
103 Uint,
104 Fixed,
105 String,
106 Object,
107 Array,
108 Fd,
109}
110
111#[derive(Clone, Default, Debug, Eq, PartialEq)]
112#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
113pub struct Enum {
114 pub name: String,
115 pub since: u32,
116 pub bitfield: bool,
117 pub description: Option<Description>,
118 pub entries: Vec<Entry>,
119}
120
121#[derive(Clone, Default, Debug, Eq, PartialEq)]
122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
123pub struct Entry {
124 pub name: String,
125 pub value: u32,
126 pub summary: Option<String>,
127 pub since: u32,
128 pub description: Option<Description>,
129}
130
131#[derive(Clone, Default, Debug, Eq, PartialEq)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub struct Description {
134 pub summary: String,
135 pub body: String,
136}
137
138impl Default for ArgKind {
139 fn default() -> Self {
140 Self::NewId
141 }
142}
143
144impl FromStr for ArgKind {
145 type Err = Error;
146 fn from_str(s: &str) -> Result<Self> {
147 Ok(match s {
148 "new_id" => ArgKind::NewId,
149 "int" => ArgKind::Int,
150 "uint" => ArgKind::Uint,
151 "fixed" => ArgKind::Fixed,
152 "string" => ArgKind::String,
153 "object" => ArgKind::Object,
154 "array" => ArgKind::Array,
155 "fd" => ArgKind::Fd,
156 _ => return Err(Error::InvalidArgKind(s.into())),
157 })
158 }
159}
160
161struct ParseContext<R: Read> {
162 event_reader: EventReader<R>,
163 attributes: Vec<OwnedAttribute>,
164}
165
166impl<R: Read> ParseContext<R> {
167 fn next(&mut self) -> Result<XmlEvent> {
168 Ok(self.event_reader.next()?)
169 }
170
171 fn attr<T>(&self, name: &str) -> Result<T>
172 where
173 T: FromStr,
174 <T as FromStr>::Err: Into<Error>,
175 {
176 Ok(self
177 .attributes
178 .iter()
179 .filter(|attr| attr.name.local_name == name)
180 .map(|attr| attr.value.clone())
181 .next()
182 .ok_or_else(|| Error::MissingRequiredAttribute(name.into()))?
183 .parse::<T>()
184 .map_err(|err| err.into())?)
185 }
186
187 fn parse(&mut self) -> Result<Protocol> {
188 Ok(loop {
189 match self.next()? {
190 StartElement {
191 name, attributes, ..
192 } if name.local_name == "protocol" => {
193 self.attributes = attributes;
194 break self.protocol()?;
195 },
196 EndDocument => return Err(Error::NoProtocol),
197 _ => {},
198 }
199 })
200 }
201
202 fn protocol(&mut self) -> Result<Protocol> {
203 let mut protocol = Protocol::default();
204 protocol.name = self.attr("name")?;
205 Ok(loop {
206 match self.next()? {
207 StartElement {
208 name, attributes, ..
209 } => {
210 self.attributes = attributes;
211 match &*name.local_name {
212 "copyright" => protocol.copyright = self.copyright()?,
213 "description" => protocol.description = self.description()?.into(),
214 "interface" => protocol.interfaces.push(self.interface()?),
215 other => return Err(Error::UnexpectedXmlElement(other.into())),
216 }
217 },
218 EndElement { name } if name.local_name == "protocol" => break protocol,
219 other => return Err(Error::UnexpectedXmlEvent(other)),
220 }
221 })
222 }
223
224 fn copyright(&mut self) -> Result<String> {
225 let mut body = None;
226 Ok(loop {
227 match self.next()? {
228 Characters(data) => body = Some(data),
229 EndElement { name } if name.local_name == "copyright" => {
230 break body.unwrap_or_default();
231 },
232 other => return Err(Error::UnexpectedXmlEvent(other)),
233 }
234 })
235 }
236
237 fn interface(&mut self) -> Result<Interface> {
238 let mut interface = Interface::default();
239 interface.name = self.attr("name")?;
240 interface.version = self.attr("version")?;
241 Ok(loop {
242 match self.next()? {
243 StartElement {
244 name, attributes, ..
245 } => {
246 self.attributes = attributes;
247 match &*name.local_name {
248 "description" => interface.description = self.description()?.into(),
249 "request" => interface.requests.push(self.request()?),
250 "event" => interface.events.push(self.event()?),
251 "enum" => interface.enums.push(self.enumeration()?),
252 other => return Err(Error::UnexpectedXmlElement(other.into())),
253 }
254 },
255 EndElement { name } if name.local_name == "interface" => break interface,
256 other => return Err(Error::UnexpectedXmlEvent(other)),
257 }
258 })
259 }
260
261 fn request(&mut self) -> Result<Request> {
262 let mut request = Request::default();
263 request.name = self.attr("name")?;
264 request.destructor = self
265 .attr("type")
266 .map(|t: String| t == "destructor")
267 .unwrap_or(false);
268 request.since = self.attr("since").unwrap_or(1);
269 Ok(loop {
270 match self.next()? {
271 StartElement {
272 name, attributes, ..
273 } => {
274 self.attributes = attributes;
275 match &*name.local_name {
276 "description" => request.description = self.description()?.into(),
277 "arg" => request.args.push(self.arg()?),
278 other => return Err(Error::UnexpectedXmlElement(other.into())),
279 }
280 },
281 EndElement { name } if name.local_name == "request" => break request,
282 other => return Err(Error::UnexpectedXmlEvent(other)),
283 }
284 })
285 }
286
287 fn event(&mut self) -> Result<Event> {
288 let mut event = Event::default();
289 event.name = self.attr("name")?;
290 event.since = self.attr("since").unwrap_or(1);
291 Ok(loop {
292 match self.next()? {
293 StartElement {
294 name, attributes, ..
295 } => {
296 self.attributes = attributes;
297 match &*name.local_name {
298 "description" => event.description = self.description()?.into(),
299 "arg" => event.args.push(self.arg()?),
300 other => return Err(Error::UnexpectedXmlElement(other.into())),
301 }
302 },
303 EndElement { name } if name.local_name == "event" => break event,
304 other => return Err(Error::UnexpectedXmlEvent(other)),
305 }
306 })
307 }
308
309 fn arg(&mut self) -> Result<Arg> {
310 let mut arg = Arg::default();
311 arg.name = self.attr("name")?;
312 arg.kind = self.attr("type")?;
313 arg.summary = self.attr("summary").ok();
314 arg.interface = self.attr("interface").ok();
315 arg.allow_null = self.attr("allow-null").unwrap_or(false);
316 arg.enumeration = self.attr("enum").ok();
317 Ok(loop {
318 match self.next()? {
319 StartElement {
320 name, attributes, ..
321 } if name.local_name == "description" => {
322 self.attributes = attributes;
323 arg.description = self.description()?.into();
324 },
325 EndElement { name } if name.local_name == "arg" => break arg,
326 other => return Err(Error::UnexpectedXmlEvent(other)),
327 }
328 })
329 }
330
331 fn enumeration(&mut self) -> Result<Enum> {
332 let mut enumeration = Enum::default();
333 enumeration.name = self.attr("name")?;
334 enumeration.since = self.attr("since").unwrap_or(1);
335 enumeration.bitfield = self.attr("bitfield").unwrap_or(false);
336 Ok(loop {
337 match self.next()? {
338 StartElement {
339 name, attributes, ..
340 } => {
341 self.attributes = attributes;
342 match &*name.local_name {
343 "description" => enumeration.description = self.description()?.into(),
344 "entry" => enumeration.entries.push(self.entry()?),
345 other => return Err(Error::UnexpectedXmlElement(other.into())),
346 }
347 },
348 EndElement { name } if name.local_name == "enum" => break enumeration,
349 other => return Err(Error::UnexpectedXmlEvent(other)),
350 }
351 })
352 }
353
354 fn entry(&mut self) -> Result<Entry> {
355 let mut entry = Entry::default();
356 entry.name = self.attr("name")?;
357 entry.value = {
358 let value: String = self.attr("value")?;
359 let (str, radix) = if value.starts_with("0x") {
360 (&value[2..], 16)
361 } else {
362 (&value[..], 10)
363 };
364 u32::from_str_radix(str, radix)?
365 };
366 entry.summary = self.attr("summary").ok();
367 entry.since = self.attr("since").unwrap_or(1);
368 Ok(loop {
369 match self.next()? {
370 StartElement {
371 name, attributes, ..
372 } if name.local_name == "description" => {
373 self.attributes = attributes;
374 entry.description = self.description()?.into();
375 },
376 EndElement { name } if name.local_name == "entry" => break entry,
377 other => return Err(Error::UnexpectedXmlEvent(other)),
378 }
379 })
380 }
381
382 fn description(&mut self) -> Result<Description> {
383 let mut description = Description::default();
384 description.summary = self.attr("summary")?;
385 Ok(loop {
386 match self.next()? {
387 Characters(data) => description.body = data,
388 EndElement { name } if name.local_name == "description" => {
389 break description;
390 },
391 other => return Err(Error::UnexpectedXmlEvent(other)),
392 }
393 })
394 }
395}
396
397pub fn parse<R: Read>(reader: R) -> std::result::Result<Protocol, Error> {
398 let event_reader = EventReader::new_with_config(
399 reader,
400 ParserConfig::new()
401 .trim_whitespace(true)
402 .cdata_to_characters(true),
403 );
404 ParseContext {
405 event_reader,
406 attributes: Vec::new(),
407 }
408 .parse()
409}