use quick_xml::name::{ResolveResult, Namespace, LocalName, QName}; use quick_xml::{Result, NsReader}; use quick_xml::events::Event; use tokio::io::AsyncBufRead; pub static XMLNS: &'static str = "http://etherx.jabber.org/streams"; #[derive(Debug, PartialEq, Eq)] pub struct ClientStreamStart { pub to: String, pub lang: String, pub version: String, } impl ClientStreamStart { pub async fn parse(reader: &mut NsReader, buf: &mut Vec) -> Result { if let Event::Start(e) = reader.read_event_into_async(buf).await? { let (ns, local) = reader.resolve_element(e.name()); if ns != ResolveResult::Bound(Namespace(XMLNS.as_bytes())) { return Err(panic!()); } if local.into_inner() != b"stream" { return Err(panic!()); } let mut to = None; let mut lang = None; let mut version = None; for attr in e.attributes() { let attr = attr?; let (ns, name) = reader.resolve_attribute(attr.key); match (ns, name.into_inner()) { (ResolveResult::Unbound, b"to") => { let value = attr.unescape_value()?; to = Some(value.to_string()); }, (ResolveResult::Bound(Namespace(b"http://www.w3.org/XML/1998/namespace")), b"lang") => { let value = attr.unescape_value()?; lang = Some(value.to_string()); }, (ResolveResult::Unbound, b"version") => { let value = attr.unescape_value()?; version = Some(value.to_string()); }, _ => {}, } } Ok(ClientStreamStart { to: to.unwrap(), lang: lang.unwrap(), version: version.unwrap() }) } else { Err(panic!()) } } } #[cfg(test)] mod test { use super::*; #[tokio::test] async fn stream_start_correct() { let input = r###""###; let mut reader = NsReader::from_reader(input.as_bytes()); let mut buf = vec![]; let res = ClientStreamStart::parse(&mut reader, &mut buf).await.unwrap(); assert_eq!(res, ClientStreamStart { to: "vlnv.dev".to_owned(), lang: "en".to_owned(), version: "1.0".to_owned()}) } }