diff --git a/src/protos/xmpp/client.rs b/src/protos/xmpp/client.rs index 6834947..8330a1d 100644 --- a/src/protos/xmpp/client.rs +++ b/src/protos/xmpp/client.rs @@ -402,132 +402,75 @@ impl PresenceShow { } } -#[derive(From)] -pub struct PresenceParser(PresenceParserInner); -enum PresenceParserInner { - Initial, - InPresence(Presence), - InPriority(Presence), - InPriorityEnd(Presence), - InShow(Presence), - InShowEnd(Presence), - InStatus(Presence), - InStatusEnd(Presence), - InCustom(Presence, T::P), -} - -impl Parser for PresenceParser { - type Output = Result>; - - fn consume<'a>( - self: Self, - namespace: ResolveResult, - event: &Event<'a>, - ) -> Continuation { - match self.0 { - PresenceParserInner::Initial => match event { - //TODO validate - Event::Start(bytes) => Continuation::Continue( - PresenceParserInner::InPresence(Presence::default()).into(), - ), - Event::Empty(bytes) => Continuation::Final(Ok(Presence::default())), - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InPresence(p) => match event { - Event::Start(bytes) => match bytes.name().0 { - b"show" => Continuation::Continue(PresenceParserInner::InShow(p).into()), - b"status" => Continuation::Continue(PresenceParserInner::InStatus(p).into()), - b"priority" => { - Continuation::Continue(PresenceParserInner::InPriority(p).into()) - } - _ => PresenceParser(PresenceParserInner::InCustom(p, T::parse())) - .consume(namespace, event), - }, - Event::Empty(_) => PresenceParser(PresenceParserInner::InCustom(p, T::parse())) - .consume(namespace, event), - Event::End(_) => Continuation::Final(Ok(p)), - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InPriority(p) => match event { - Event::Text(bytes) => { - match (|| { - let s = std::str::from_utf8(bytes)?; - let i = s.parse()?; - Ok(Presence { - priority: Some(PresencePriority(i)), - ..p - }) - })() { - Ok(res) => { - Continuation::Continue(PresenceParserInner::InPriorityEnd(res).into()) - } - Err(e) => Continuation::Final(Err(e)), - } - } - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InPriorityEnd(p) => match event { - Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()), - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InShow(p) => match event { - Event::Text(bytes) => { - match (|| { - let i = PresenceShow::from_str(bytes)?; - Ok(Presence { show: Some(i), ..p }) - })() { - Ok(res) => { - Continuation::Continue(PresenceParserInner::InShowEnd(res).into()) - } - Err(e) => Continuation::Final(Err(e)), - } - } - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InShowEnd(p) => match event { - Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()), - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InStatus(mut p) => match event { - Event::Text(bytes) => { - match (|| { - let i = std::str::from_utf8(bytes)?; - p.status.push(i.to_string()); - Ok(p) - })() { - Ok(res) => { - Continuation::Continue(PresenceParserInner::InStatusEnd(res).into()) - } - Err(e) => Continuation::Final(Err(e)), - } - } - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InStatusEnd(p) => match event { - Event::End(_) => Continuation::Continue(PresenceParserInner::InPresence(p).into()), - _ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))), - }, - PresenceParserInner::InCustom(mut p, c) => match c.consume(namespace, event) { - Continuation::Final(Ok(res)) => { - p.custom.push(res); - Continuation::Continue(PresenceParserInner::InPresence(p).into()) - } - Continuation::Final(Err(err)) => Continuation::Final(Err(ffail!( - "Failed to parse custom presence element: {err}" - ))), - Continuation::Continue(c) => { - Continuation::Continue(PresenceParserInner::InCustom(p, c).into()) - } - }, - } - } -} - impl FromXml for Presence { - type P = PresenceParser; + type P = impl Parser>>; fn parse() -> Self::P { - PresenceParserInner::Initial.into() + |(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result { + let _ = match event { + Event::Start(bytes) => bytes, + Event::Empty(_) => return Ok(Presence::default()), + _ => return Err(ffail!("Unexpected XML event: {event:?}")), + }; + let mut p = Presence::::default(); + loop { + let (namespace, event) = yield; + match event { + Event::Start(bytes) => match bytes.name().0 { + b"show" => { + let (_, event) = yield; + let Event::Text(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + let i = PresenceShow::from_str(bytes)?; + p.show = Some(i); + + let (_, event) = yield; + let Event::End(_) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + } + b"status" => { + let (_, event) = yield; + let Event::Text(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + let s = std::str::from_utf8(bytes)?; + p.status.push(s.to_string()); + + let (_, event) = yield; + let Event::End(_) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + } + b"priority" => { + let (_, event) = yield; + let Event::Text(bytes) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + let s = std::str::from_utf8(bytes)?; + let i = s.parse()?; + p.priority = Some(PresencePriority(i)); + + let (_, event) = yield; + let Event::End(_) = event else { + return Err(ffail!("Unexpected XML event: {event:?}")); + }; + } + _ => { + let res = delegate_parsing!(T, namespace, event); + p.custom.push(res?); + } + }, + Event::Empty(_) => { + let res = delegate_parsing!(T, namespace, event); + p.custom.push(res?); + } + Event::End(_) => return Ok(p), + _ => return Err(ffail!("Unexpected XML event: {event:?}")), + } + } + } } }