forked from lavina/lavina
rewrite presence parser as a generator
This commit is contained in:
parent
d0f807841c
commit
9110ab9beb
|
@ -402,132 +402,75 @@ impl PresenceShow {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
pub struct PresenceParser<T: FromXml>(PresenceParserInner<T>);
|
||||
enum PresenceParserInner<T: FromXml> {
|
||||
Initial,
|
||||
InPresence(Presence<T>),
|
||||
InPriority(Presence<T>),
|
||||
InPriorityEnd(Presence<T>),
|
||||
InShow(Presence<T>),
|
||||
InShowEnd(Presence<T>),
|
||||
InStatus(Presence<T>),
|
||||
InStatusEnd(Presence<T>),
|
||||
InCustom(Presence<T>, T::P),
|
||||
}
|
||||
|
||||
impl<T: FromXml> Parser for PresenceParser<T> {
|
||||
type Output = Result<Presence<T>>;
|
||||
|
||||
fn consume<'a>(
|
||||
self: Self,
|
||||
namespace: ResolveResult,
|
||||
event: &Event<'a>,
|
||||
) -> Continuation<Self, Self::Output> {
|
||||
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<T: FromXml> FromXml for Presence<T> {
|
||||
type P = PresenceParser<T>;
|
||||
type P = impl Parser<Output = Result<Presence<T>>>;
|
||||
|
||||
fn parse() -> Self::P {
|
||||
PresenceParserInner::Initial.into()
|
||||
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
|
||||
let _ = match event {
|
||||
Event::Start(bytes) => bytes,
|
||||
Event::Empty(_) => return Ok(Presence::default()),
|
||||
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
|
||||
};
|
||||
let mut p = Presence::<T>::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:?}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue