Improve error reporting

This commit is contained in:
Dirkjan Ochtman 2022-11-23 18:53:40 -08:00
parent f6e22b3e31
commit eb2cfd59f9
5 changed files with 54 additions and 27 deletions

View File

@ -132,7 +132,7 @@ fn deserialize_wrapped_enum(
let data = match node {
Node::Open(data) => data,
_ => return Err(Error::UnexpectedState),
_ => return Err(Error::UnexpectedState("unexpected node type for wrapped enum variant")),
};
let id = deserializer.element_id(&data)?;
@ -141,7 +141,7 @@ fn deserialize_wrapped_enum(
};
if let Some(_) = deserializer.next() {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("unexpected node after wrapped enum variant"));
}
Ok(value)
@ -278,7 +278,7 @@ fn deserialize_struct(
}
}
}
_ => return Err(Error::UnexpectedState),
node => return Err(Error::UnexpectedNode(format!("{:?}", node))),
}
}

View File

@ -36,7 +36,11 @@ impl<'cx, 'xml> Deserializer<'cx, 'xml> {
if element {
match self.next() {
Some(Ok(_)) => return Err(Error::UnexpectedState),
Some(Ok(_)) => {
return Err(Error::UnexpectedState(
"found element while expecting scalar",
))
}
Some(Err(e)) => return Err(e),
_ => {}
}
@ -112,7 +116,7 @@ impl<'xml> Iterator for Deserializer<'_, 'xml> {
return None;
}
Some(Err(Error::UnexpectedState))
Some(Err(Error::UnexpectedState("close element mismatch")))
}
}
@ -133,7 +137,7 @@ impl<'xml> Context<'xml> {
let root = match new.next() {
Some(result) => match result? {
Node::Open(element) => element,
_ => return Err(Error::UnexpectedState),
_ => return Err(Error::UnexpectedState("first node does not open element")),
},
None => return Err(Error::UnexpectedEndOfStream),
};
@ -217,7 +221,11 @@ impl<'xml> Iterator for Context<'xml> {
ElementEnd::Open => {
let level = match current {
Some(level) => level,
None => return Some(Err(Error::UnexpectedState)),
None => {
return Some(Err(Error::UnexpectedState(
"opening element with no parent",
)))
}
};
let element = Element {
@ -232,7 +240,11 @@ impl<'xml> Iterator for Context<'xml> {
ElementEnd::Close(prefix, v) => {
let level = match self.stack.pop() {
Some(level) => level,
None => return Some(Err(Error::UnexpectedState)),
None => {
return Some(Err(Error::UnexpectedState(
"closing element without parent",
)))
}
};
let prefix = (!prefix.is_empty()).then_some(prefix.as_str());
@ -243,7 +255,9 @@ impl<'xml> Iterator for Context<'xml> {
local: level.local,
}))
}
false => return Some(Err(Error::UnexpectedState)),
false => {
return Some(Err(Error::UnexpectedState("close element mismatch")))
}
}
}
ElementEnd::Empty => {
@ -259,14 +273,22 @@ impl<'xml> Iterator for Context<'xml> {
if prefix.is_empty() && local.as_str() == "xmlns" {
match &mut current {
Some(level) => level.default_ns = Some(value.as_str()),
None => return Some(Err(Error::UnexpectedState)),
None => {
return Some(Err(Error::UnexpectedState(
"attribute without element context",
)))
}
}
} else if prefix.as_str() == "xmlns" {
match &mut current {
Some(level) => {
level.prefixes.insert(local.as_str(), value.as_str());
}
None => return Some(Err(Error::UnexpectedState)),
None => {
return Some(Err(Error::UnexpectedState(
"attribute without element context",
)))
}
}
} else {
let prefix = (!prefix.is_empty()).then_some(prefix.as_str());
@ -280,7 +302,7 @@ impl<'xml> Iterator for Context<'xml> {
Ok(Token::Text { text }) => {
return Some(Ok(Node::Text(text.as_str())));
}
Ok(_) => return Some(Err(Error::UnexpectedToken)),
Ok(token) => return Some(Err(Error::UnexpectedToken(format!("{:?}", token)))),
Err(e) => return Some(Err(Error::Parse(e))),
}
}

View File

@ -341,14 +341,14 @@ where
let mut nested = deserializer.nested(data);
result.push(<T as FromXml<'xml>>::deserialize(&mut nested)?)
}
_ => return Err(Error::UnexpectedState),
_ => return Err(Error::UnexpectedState("unexpected list element name")),
}
}
(Kind::Vec | Kind::Element(_), Node::Open(data)) => {
let mut nested = deserializer.nested(data);
result.push(<T as FromXml<'xml>>::deserialize(&mut nested)?)
}
_ => return Err(Error::UnexpectedState),
_ => return Err(Error::UnexpectedState("unexpected node for list")),
}
}

View File

@ -49,8 +49,8 @@ pub fn from_str<'xml, T: FromXml<'xml>>(input: &'xml str) -> Result<T, Error> {
let (mut context, root) = Context::new(input)?;
let id = context.element_id(&root)?;
let expected = match T::KIND {
Kind::Scalar => return Err(Error::UnexpectedState),
Kind::Vec => return Err(Error::UnexpectedState),
Kind::Scalar => return Err(Error::UnexpectedState("found scalar as root")),
Kind::Vec => return Err(Error::UnexpectedState("found list as root")),
Kind::Element(expected) => expected,
};
@ -96,12 +96,14 @@ pub enum Error {
MissingTag,
#[error("missing value")]
MissingValue,
#[error("unexpected token")]
UnexpectedToken,
#[error("unexpected token: {0}")]
UnexpectedToken(String),
#[error("missing prefix")]
MissingdPrefix,
#[error("unexpected state")]
UnexpectedState,
#[error("unexpected node: {0}")]
UnexpectedNode(String),
#[error("unexpected state: {0}")]
UnexpectedState(&'static str),
#[error("expected scalar")]
ExpectedScalar,
#[error("wrong namespace")]

View File

@ -35,7 +35,7 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
scalar: bool,
) -> Result<Option<&'static str>, Error> {
if self.state != State::Element {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for element start"));
}
let prefix = match ns == self.default_ns {
@ -70,13 +70,16 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
value: &V,
) -> Result<(), Error> {
if self.state != State::Attribute {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for attribute"));
}
match ns == self.default_ns {
true => self.output.write_fmt(format_args!(" {name}=\""))?,
false => {
let prefix = self.prefixes.get(ns).ok_or(dbg!(Error::UnexpectedState))?;
let prefix = self
.prefixes
.get(ns)
.ok_or(Error::UnexpectedState("unknown prefix"))?;
self.output.write_fmt(format_args!(" {prefix}:{name}=\""))?;
}
}
@ -90,7 +93,7 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
pub fn write_str<V: fmt::Display + ?Sized>(&mut self, value: &V) -> Result<(), Error> {
if !matches!(self.state, State::Element | State::Scalar) {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for scalar"));
}
self.output.write_fmt(format_args!("{}", value))?;
@ -100,7 +103,7 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
pub fn end_start(&mut self) -> Result<(), Error> {
if self.state != State::Attribute {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for element end"));
}
self.output.write_char('>')?;
@ -110,7 +113,7 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
pub fn write_close(&mut self, prefix: Option<&str>, name: &str) -> Result<(), Error> {
if self.state != State::Element {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for close element"));
}
match prefix {
@ -123,7 +126,7 @@ impl<'xml, W: fmt::Write + ?Sized> Serializer<'xml, W> {
pub fn push<const N: usize>(&mut self, new: Context<N>) -> Result<Context<N>, Error> {
if self.state != State::Attribute {
return Err(Error::UnexpectedState);
return Err(Error::UnexpectedState("invalid state for attribute"));
}
let mut old = Context::default();