#![allow(unused_variables)] use quick_xml::events::Event; use quick_xml::name::ResolveResult; use crate::xml::*; use anyhow::{anyhow, Result}; pub const XMLNS: &'static str = "http://jabber.org/protocol/muc"; #[derive(PartialEq, Eq, Debug, Default)] pub struct History { pub maxchars: Option, pub maxstanzas: Option, pub seconds: Option, } impl FromXml for History { type P = impl Parser>; fn parse() -> Self::P { |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { let mut history = History::default(); let (bytes, end) = match event { Event::Start(bytes) if bytes.name().0 == Self::NAME.as_bytes() => (bytes, false), Event::Empty(bytes) if bytes.name().0 == Self::NAME.as_bytes() => (bytes, true), _ => return Err(anyhow!("Unexpected XML event: {event:?}")), }; for attr in bytes.attributes() { let attr = attr?; match attr.key.0 { b"maxchars" => { let s = std::str::from_utf8(&attr.value)?; let a = s.parse()?; history.maxchars = Some(a) } b"maxstanzas" => { let s = std::str::from_utf8(&attr.value)?; let a = s.parse()?; history.maxstanzas = Some(a) } b"seconds" => { let s = std::str::from_utf8(&attr.value)?; let a = s.parse()?; history.seconds = Some(a) } _ => {} } } if end { return Ok(history); } let (namespace, event) = yield; let Event::End(bytes) = event else { return Err(anyhow!("Unexpected XML event: {event:?}")); }; Ok(history) } } } impl FromXmlTag for History { const NAME: &'static str = "history"; const NS: &'static str = XMLNS; } #[derive(PartialEq, Eq, Debug)] pub struct Password(pub String); impl FromXml for Password { type P = impl Parser>; fn parse() -> Self::P { |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { let bytes = match event { Event::Start(bytes) if bytes.name().0 == Self::NAME.as_bytes() => bytes, _ => return Err(anyhow!("Unexpected XML event: {event:?}")), }; let (namespace, event) = yield; let Event::Text(bytes) = event else { return Err(anyhow!("Unexpected XML event: {event:?}")); }; let s = std::str::from_utf8(bytes)?.to_string(); let (namespace, event) = yield; let Event::End(bytes) = event else { return Err(anyhow!("Unexpected XML event: {event:?}")); }; Ok(Password(s)) } } } impl FromXmlTag for Password { const NAME: &'static str = "password"; const NS: &'static str = XMLNS; } #[derive(PartialEq, Eq, Debug, Default)] pub struct X { pub history: Option, pub password: Option, } impl FromXml for X { type P = impl Parser>; fn parse() -> Self::P { |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { let mut res = X::default(); let (_, end) = match event { Event::Start(bytes) => (bytes, false), Event::Empty(bytes) => (bytes, true), _ => return Err(anyhow!("Unexpected XML event: {event:?}")), }; if end { return Ok(res); } loop { let (namespace, event) = yield; let bytes = match event { Event::Start(bytes) => bytes, Event::Empty(bytes) => bytes, Event::End(_) => break, _ => return Err(anyhow!("Unexpected XML event: {event:?}")), }; if bytes.name().0 == Password::NAME.as_bytes() { let password = delegate_parsing!(Password, namespace, event)?; res.password = Some(password); } else if bytes.name().0 == History::NAME.as_bytes() { let history = delegate_parsing!(History, namespace, event)?; res.history = Some(history); } else { return Err(anyhow!("Unexpected XML event: {event:?}")); } } Ok(res) } } } #[cfg(test)] mod test { use super::*; #[test] fn test_history_success_empty() { let input = ""; let res: History = parse(input).unwrap(); let expected = History { maxchars: None, maxstanzas: None, seconds: None, }; assert_eq!(res, expected); } #[test] fn test_history_success_empty_attrs() { let input = r#""#; let res: History = parse(input).unwrap(); let expected = History { maxchars: Some(1), maxstanzas: Some(2), seconds: Some(4), }; assert_eq!(res, expected); } #[test] fn test_history_success_start_end() { let input = r#""#; let res: History = parse(input).unwrap(); let expected = History { maxchars: None, maxstanzas: None, seconds: None, }; assert_eq!(res, expected); } #[test] fn test_history_incorrect_empty() { let input = r#""#; parse::(input).err().unwrap(); } #[test] fn test_password_success() { let input = "olala"; let res: Password = parse(input).unwrap(); let expected = Password("olala".into()); assert_eq!(res, expected); } #[test] fn test_password_incorrect() { let input = r#"asdsd"#; parse::(input).err().unwrap(); } #[test] fn test_x_success_empty() { let input = ""; let res: X = parse(input).unwrap(); let expected = X { history: None, password: None, }; assert_eq!(res, expected); } #[test] fn test_x_success_full() { let input = r#"ololo"#; let res: X = parse(input).unwrap(); let expected = X { history: Some(History { maxchars: Some(1), maxstanzas: None, seconds: None, }), password: Some(Password("ololo".into())), }; assert_eq!(res, expected); } }