xso: introduce xso::from_bytes
This is useful both for doctests and other scenarios where you just want to parse a bit of XML you already have.
This commit is contained in:
parent
6ef8dbefa3
commit
9ec9a0f0c6
1 changed files with 55 additions and 0 deletions
|
@ -173,3 +173,58 @@ pub fn try_from_element<T: FromXml>(
|
|||
// implementations must be constructible from that.
|
||||
unreachable!("minidom::Element did not produce enough events to complete element")
|
||||
}
|
||||
|
||||
fn map_nonio_error<T>(r: Result<T, rxml::Error>) -> Result<T, self::error::Error> {
|
||||
match r {
|
||||
Ok(v) => Ok(v),
|
||||
Err(rxml::Error::IO(_)) => unreachable!(),
|
||||
Err(rxml::Error::Xml(e)) => Err(e.into()),
|
||||
Err(rxml::Error::InvalidUtf8Byte(_)) => Err(self::error::Error::Other("invalid utf-8")),
|
||||
Err(rxml::Error::InvalidChar(_)) => {
|
||||
Err(self::error::Error::Other("non-character encountered"))
|
||||
}
|
||||
Err(rxml::Error::RestrictedXml(_)) => Err(self::error::Error::Other("restricted xml")),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_start_event<I: std::io::BufRead>(
|
||||
r: &mut rxml::Reader<I>,
|
||||
) -> Result<(rxml::QName, rxml::AttrMap), self::error::Error> {
|
||||
for ev in r {
|
||||
match map_nonio_error(ev)? {
|
||||
rxml::Event::XmlDeclaration(_, rxml::XmlVersion::V1_0) => (),
|
||||
rxml::Event::StartElement(_, name, attrs) => return Ok((name, attrs)),
|
||||
_ => {
|
||||
return Err(self::error::Error::Other(
|
||||
"Unexpected event at start of document",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(self::error::Error::XmlError(
|
||||
rxml::error::XmlError::InvalidEof("before start of element"),
|
||||
))
|
||||
}
|
||||
|
||||
/// Attempt to parse a type implementing [`FromXml`] from a byte buffer
|
||||
/// containing XML data.
|
||||
pub fn from_bytes<T: FromXml>(mut buf: &[u8]) -> Result<T, self::error::Error> {
|
||||
let mut reader = rxml::Reader::new(&mut buf);
|
||||
let (name, attrs) = read_start_event(&mut reader)?;
|
||||
let mut builder = match T::from_events(name, attrs) {
|
||||
Ok(v) => v,
|
||||
Err(self::error::FromEventsError::Mismatch { .. }) => {
|
||||
return Err(self::error::Error::TypeMismatch)
|
||||
}
|
||||
Err(self::error::FromEventsError::Invalid(e)) => return Err(e),
|
||||
};
|
||||
for ev in reader {
|
||||
match builder.feed(map_nonio_error(ev)?)? {
|
||||
Some(v) => return Ok(v),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
Err(self::error::Error::XmlError(
|
||||
rxml::error::XmlError::InvalidEof("while parsing FromXml impl"),
|
||||
))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue