wayland_protocol_parser/
lib.rs

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}