From c18ace62302117063013f5c6d69de416b80a75d7 Mon Sep 17 00:00:00 2001 From: lumi Date: Sun, 19 Feb 2017 21:00:59 +0100 Subject: [PATCH] put DOM stuff into a separate crate: minidom-rs --- Cargo.toml | 3 + src/error.rs | 8 ++ src/lib.rs | 2 +- src/transport.rs | 14 +-- src/tree.rs | 279 ----------------------------------------------- 5 files changed, 19 insertions(+), 287 deletions(-) delete mode 100644 src/tree.rs diff --git a/Cargo.toml b/Cargo.toml index 5394c8b..34dab76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,6 @@ authors = ["lumi "] [dependencies] xml-rs = "*" openssl = "*" + +[dependencies.minidom] +git = "https://gitlab.com/lumi/minidom-rs.git" diff --git a/src/error.rs b/src/error.rs index f4af81d..87f5ef4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,6 +8,8 @@ use openssl::error::ErrorStack; use xml::reader::Error as XmlError; use xml::writer::Error as EmitterError; +use minidom::error::Error as MinidomError; + #[derive(Debug)] pub enum Error { XmlError(XmlError), @@ -15,6 +17,7 @@ pub enum Error { IoError(io::Error), HandshakeError(HandshakeError), OpenSslErrorStack(ErrorStack), + MinidomError(MinidomError), StreamError, EndOfDocument, } @@ -49,3 +52,8 @@ impl From for Error { } } +impl From for Error { + fn from(err: MinidomError) -> Error { + Error::MinidomError(err) + } +} diff --git a/src/lib.rs b/src/lib.rs index 08a2997..6baaae7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,11 @@ extern crate xml; extern crate openssl; +extern crate minidom; pub mod ns; pub mod transport; pub mod error; pub mod jid; pub mod client; -pub mod tree; mod locked_io; diff --git a/src/transport.rs b/src/transport.rs index b7b299d..289b6d6 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex}; use ns; -use tree; +use minidom; use locked_io::LockedIO; @@ -21,8 +21,8 @@ pub trait Transport { fn write_event<'a, E: Into>>(&mut self, event: E) -> Result<(), Error>; fn read_event(&mut self) -> Result; - fn write_element(&mut self, element: &tree::Element) -> Result<(), Error>; - fn read_element(&mut self) -> Result; + fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error>; + fn read_element(&mut self) -> Result; } pub struct SslTransport { @@ -42,12 +42,12 @@ impl Transport for SslTransport { Ok(self.reader.next()?) } - fn write_element(&mut self, element: &tree::Element) -> Result<(), Error> { - element.write_to(&mut self.writer) + fn write_element(&mut self, element: &minidom::Element) -> Result<(), Error> { + Ok(element.write_to(&mut self.writer)?) } - fn read_element(&mut self) -> Result { - tree::Element::from_reader(&mut self.reader) + fn read_element(&mut self) -> Result { + Ok(minidom::Element::from_reader(&mut self.reader)?) } } diff --git a/src/tree.rs b/src/tree.rs deleted file mode 100644 index 339f1a5..0000000 --- a/src/tree.rs +++ /dev/null @@ -1,279 +0,0 @@ -// TODO: really should either be a separate crate or implemented into xml-rs - -use std::io::prelude::*; - -use std::convert::From; - -use std::fmt; - -use xml::name::{OwnedName, Name}; -use xml::reader::{XmlEvent as ReaderEvent, EventReader}; -use xml::writer::{XmlEvent as WriterEvent, EventWriter}; -use xml::attribute::OwnedAttribute; - -use error::Error; - -#[derive(Clone, PartialEq, Eq)] -pub struct Element { - name: OwnedName, - attributes: Vec, - children: Vec, -} - -impl fmt::Debug for Element { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "<{}", self.name)?; - for attr in &self.attributes { - write!(fmt, " {}", attr)?; - } - write!(fmt, ">")?; - for child in &self.children { - match *child { - Fork::Element(ref e) => { - write!(fmt, "{:?}", e)?; - }, - Fork::Text(ref s) => { - write!(fmt, "{}", s)?; - }, - } - } - write!(fmt, "", self.name)?; - Ok(()) - } -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Fork { - Element(Element), - Text(String), -} - -impl Element { - pub fn new(name: OwnedName, attributes: Vec) -> Element { - Element { - name: name, - attributes: attributes, - children: Vec::new(), - } - } - - pub fn builder>(name: S) -> ElementBuilder { - ElementBuilder { - name: OwnedName::local(name), - attributes: Vec::new(), - } - } - - pub fn tag(&self) -> &str { - &self.name.local_name - } - - pub fn ns(&self) -> Option<&str> { - self.name.namespace.as_ref() - .map(String::as_ref) - } - - pub fn attr(&self, key: &str) -> Option<&str> { - for attr in &self.attributes { - if attr.name.local_name == key { - return Some(&attr.value); - } - } - None - } - - pub fn from_reader(reader: &mut EventReader) -> Result { - loop { - let e = reader.next()?; - match e { - ReaderEvent::StartElement { name, attributes, .. } => { - let mut root = Element::new(name, attributes); - root.from_reader_inner(reader); - return Ok(root); - }, - ReaderEvent::EndDocument => { - return Err(Error::EndOfDocument); - }, - _ => () // TODO: may need more errors - } - } - } - - fn from_reader_inner(&mut self, reader: &mut EventReader) -> Result<(), Error> { - loop { - let e = reader.next()?; - match e { - ReaderEvent::StartElement { name, attributes, .. } => { - let elem = Element::new(name, attributes); - let elem_ref = self.append_child(elem); - elem_ref.from_reader_inner(reader); - }, - ReaderEvent::EndElement { .. } => { - // TODO: may want to check whether we're closing the correct element - return Ok(()); - }, - ReaderEvent::Characters(s) => { - self.append_text_node(s); - }, - ReaderEvent::CData(s) => { - self.append_text_node(s); - }, - ReaderEvent::EndDocument => { - return Err(Error::EndOfDocument); - }, - _ => (), // TODO: may need to implement more - } - } - } - - pub fn write_to(&self, writer: &mut EventWriter) -> Result<(), Error> { - let mut start = WriterEvent::start_element(self.name.borrow()); - if let Some(ref ns) = self.name.namespace { - start = start.default_ns(ns.as_ref()); - } - for attr in &self.attributes { // TODO: I think this could be done a lot more efficiently - start = start.attr(attr.name.borrow(), &attr.value); - } - writer.write(start)?; - for child in &self.children { - match *child { - Fork::Element(ref e) => { - e.write_to(writer)?; - }, - Fork::Text(ref s) => { - writer.write(WriterEvent::characters(s))?; - }, - } - } - writer.write(WriterEvent::end_element())?; - Ok(()) - } - - pub fn children<'a>(&'a self) -> Children<'a> { - unimplemented!(); - } - - pub fn children_mut<'a>(&'a mut self) -> ChildrenMut<'a> { - unimplemented!(); - } - - pub fn append_child(&mut self, child: Element) -> &mut Element { - self.children.push(Fork::Element(child)); - if let Fork::Element(ref mut cld) = *self.children.last_mut().unwrap() { - cld - } - else { - unreachable!() - } - } - - pub fn append_text_node>(&mut self, child: S) { - self.children.push(Fork::Text(child.into())); - } - - pub fn text(&self) -> &str { - unimplemented!() - } - - pub fn get_child<'a, N: Into>>(&self, name: N) -> Option<&Element> { - unimplemented!() - } - - pub fn get_child_mut<'a, N: Into>>(&mut self, name: N) -> Option<&mut Element> { - unimplemented!() - } - - pub fn into_child<'a, N: Into>>(self, name: N) -> Option { - unimplemented!() - } -} - -pub struct Children<'a> { - elem: &'a Element, -} - -pub struct ChildrenMut<'a> { - elem: &'a mut Element, -} - -pub struct ElementBuilder { - name: OwnedName, - attributes: Vec, -} - -impl ElementBuilder { - pub fn ns>(mut self, namespace: S) -> ElementBuilder { - self.name.namespace = Some(namespace.into()); - self - } - - pub fn attr, V: Into>(mut self, name: S, value: V) -> ElementBuilder { - self.attributes.push(OwnedAttribute::new(OwnedName::local(name), value)); - self - } - - pub fn attr_ns, N: Into, V: Into>(mut self, name: S, namespace: N, value: V) -> ElementBuilder { - self.attributes.push(OwnedAttribute::new(OwnedName::qualified::<_, _, &'static str>(name, namespace, None), value)); - self - } - - pub fn build(self) -> Element { - Element::new(self.name, self.attributes) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - const TEST_STRING: &'static str = r#"meownya"#; - - fn build_test_tree() -> Element { - let mut root = Element::builder("root") - .ns("root_ns") - .attr("a", "b") - .build(); - root.append_text_node("meow"); - let child = Element::builder("child") - .attr("c", "d") - .build(); - root.append_child(child); - let other_child = Element::builder("child") - .ns("child_ns") - .attr("d", "e") - .build(); - root.append_child(other_child); - root.append_text_node("nya"); - root - } - - #[test] - fn reader_works() { - use std::io::Cursor; - let mut reader = EventReader::new(Cursor::new(TEST_STRING)); - // TODO: fix a bunch of namespace stuff so this test passes - assert_eq!(Element::from_reader(&mut reader).unwrap(), build_test_tree()); - } - - #[test] - fn writer_works() { - let root = build_test_tree(); - let mut out = Vec::new(); - { - let mut writer = EventWriter::new(&mut out); - root.write_to(&mut writer); - } - assert_eq!(String::from_utf8(out).unwrap(), TEST_STRING); - } - - #[test] - fn builder_works() { - let elem = Element::builder("a") - .ns("b") - .attr("c", "d") - .build(); - assert_eq!(elem.tag(), "a"); - assert_eq!(elem.ns(), Some("b")); - assert_eq!(elem.attr("c"), Some("d")); - } -}