Make TryFrom<Element> chainable

This allows constructs like:

```rust
let residual = match Iq::try_from(stanza) {
  Ok(iq) => return handle_iq(..),
  Err(Error::TypeMismatch(_, _, v)) => v,
  Err(other) => return handle_parse_error(..),
};
let residual = match Message::try_from(stanza) {
  ..
};
let residual = ..
log::warn!("unhandled object: {:?}", residual);
```

The interesting part of this is that this could be used in a loop over a
Vec<Box<dyn FnMut(Element) -> ControlFlow<SomeResult, Element>>, i.e. in
a parsing loop for a generic XML/XMPP stream.

The advantage is that the stanza.is() check runs only once (in
check_self!) and doesn't need to be duplicated outside, and it reduces
the use of magic strings.
This commit is contained in:
Jonas Schäfer 2024-03-02 09:19:49 +01:00 committed by Link Mauve
commit 2f7d5edb8a
8 changed files with 68 additions and 25 deletions

View file

@ -69,12 +69,12 @@ mod tests {
let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0'/>"
.parse()
.unwrap();
let error = Delay::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
let error = Delay::try_from(elem.clone()).unwrap_err();
let returned_elem = match error {
Error::TypeMismatch(_, _, elem) => elem,
_ => panic!(),
};
assert_eq!(message, "This is not a delay element.");
assert_eq!(elem, returned_elem);
}
#[test]