1// Copyright (c) 2020 Maxime “pep” Buquet <pep@bouah.net>
2// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8//! Provides a `Parser` type, which takes bytes and returns Elements. It also keeps a hold of
9//! ascendant elements to be able to handle namespaces properly.
10
11use crate::element::Element;
12use crate::error::{Error, ParserError, Result};
13
14use bytes::BytesMut;
15use quick_xml::Reader as EventReader;
16use std::cell::RefCell;
17use std::str;
18
19/// Parser
20#[derive(Debug)]
21pub struct Parser {
22 buffer: RefCell<BytesMut>,
23 state: ParserState,
24}
25
26/// Describes the state of the parser.
27///
28/// This parser will only accept one-level documents. The root element is kept for convenience, to
29/// be able to pass namespaces down to children who are themselves children.
30#[derive(Debug)]
31pub enum ParserState {
32 /// Not enough data has been processed to find the first element.
33 Empty,
34
35 /// The normal state. the root element has been identified and children are processed.
36 Root {
37 /// Root element. Kept for future reference
38 root: Element,
39
40 /// Child element
41 child: Option<Element>,
42
43 /// XXX: Weird flag to say if we've already sent what we could send or if there's more to
44 /// send. This Variant needs to be changed.
45 sent: bool,
46 },
47
48 /// Something was passed in the buffer that made the parser get into an error state.
49 Error,
50
51 /// The root element has been closed. No feed-ing can happen past this point.
52 Closed,
53}
54
55/// Result of polling the parser
56#[derive(Debug)]
57pub enum ParserResult {
58 /// Buffer is not empty but needs more data
59 Partial,
60
61 /// An Element has been generated from the buffer.
62 Single(Element),
63}
64
65/*
66/// Split <stream:stream> and parse it.
67fn split_stream_stream_stream_features(string: String) -> (Element, Element) {
68 let mut stuff = string.splitn(2, '>');
69 let stream_opening_str = stuff.next().unwrap().to_string() + "/>";
70 let rest = stuff.next().unwrap().to_string();
71 let stream_opening: Element = stream_opening_str.parse().unwrap();
72 let rest: Element = rest.parse().unwrap();
73 println!("opening: {}", String::from(&stream_opening));
74 println!("features: {}", String::from(&rest));
75 (stream_opening, rest)
76}
77*/
78
79fn maybe_split_prolog(string: &str) -> &str {
80 if string.starts_with("<?xml") {
81 let mut stuff = string.splitn(2, '>');
82 stuff.next();
83 stuff.next().unwrap()
84 } else {
85 string
86 }
87}
88
89impl Parser {
90 /// Creates a new Parser
91 pub fn new() -> Parser {
92 Parser {
93 buffer: RefCell::new(BytesMut::new()),
94 state: ParserState::Empty,
95 }
96 }
97
98 /// Feed bytes to the parser.
99 pub fn feed(&mut self, bytes: BytesMut) -> Result<()> {
100 self.buffer.borrow_mut().unsplit(bytes);
101 let state = match self.state {
102 ParserState::Empty => {
103 // TODO: Try splitting xml prolog and stream header
104 let foo = self.buffer.borrow();
105 let header = maybe_split_prolog(str::from_utf8(foo.as_ref())?);
106 println!("FOO: header: {:?}", header);
107 let mut reader = EventReader::from_str(header);
108 let root = Element::from_reader(&mut reader);
109 match root {
110 Ok(root) => {
111 println!("FOO: elem: {:?}", root);
112 ParserState::Root {
113 root,
114 child: None,
115 sent: false,
116 }
117 }
118 Err(e) => {
119 println!("FOO: err: {:?}", e);
120 ParserState::Empty
121 }
122 }
123 }
124 ParserState::Closed => return Err(Error::ParserError(ParserError::Closed)),
125 _ => ParserState::Empty,
126 };
127
128 self.state = state;
129 Ok(())
130 }
131
132 /// Returns Elements to the application.
133 pub fn poll(&mut self) -> Result<Option<ParserResult>> {
134 match &self.state {
135 ParserState::Empty if self.buffer.borrow().len() != 0 => {
136 Ok(Some(ParserResult::Partial))
137 }
138 ParserState::Empty | ParserState::Closed | ParserState::Error => Ok(None),
139 ParserState::Root {
140 root, child: None, ..
141 } => Ok(Some(ParserResult::Single(root.clone()))),
142 ParserState::Root {
143 child: Some(child), ..
144 } => Ok(Some(ParserResult::Single(child.clone()))),
145 }
146 }
147
148 /// Resets the parser
149 pub fn reset(&mut self) {
150 *self = Parser::new();
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use bytes::{BufMut, BytesMut};
158
159 #[test]
160 fn test_prolog() {
161 let mut parser = Parser::new();
162 let mut buf = BytesMut::new();
163 buf.put(&b"<?xml version='1.0'?>"[..]);
164 buf.put(&b"<stream:stream xmlns='jabber:client' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' to='foo.bar'>"[..]);
165 match parser.feed(buf) {
166 Ok(_) => (),
167 _ => panic!(),
168 }
169
170 let elem = Element::builder("stream:stream", "http://etherx.jabber.org/streams")
171 .prefix_ns(None, "jabber:client")
172 .attr("xml:lang", "en")
173 .attr("version", "1.0")
174 .attr("to", "foo.bar")
175 .build();
176
177 println!("BAR: elem: {:?}", elem);
178
179 match parser.poll() {
180 Ok(Some(ParserResult::Single(e))) => assert_eq!(e, elem),
181 _ => panic!(),
182 }
183 }
184}