xso: add support for ignoring unknown children
This commit is contained in:
parent
290460ba9d
commit
66233b0150
10 changed files with 242 additions and 6 deletions
|
|
@ -69,6 +69,7 @@ The following keys are defined on structs:
|
|||
| `builder` | optional *ident* | The name to use for the generated builder type. |
|
||||
| `iterator` | optional *ident* | The name to use for the generated iterator type. |
|
||||
| `on_unknown_attribute` | *identifier* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
|
||||
| `on_unknown_child` | *identifier* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |
|
||||
|
||||
Note that the `name` value must be a valid XML element name, without colons.
|
||||
The namespace prefix, if any, is assigned automatically at serialisation time
|
||||
|
|
@ -149,6 +150,7 @@ documentation above.
|
|||
| --- | --- | --- |
|
||||
| `name` | *string literal* or *path* | The XML element name to match for this variant. If it is a *path*, it must point at a `&'static NcNameStr`. |
|
||||
| `on_unknown_attribute` | *identifier* | Name of an [`UnknownAttributePolicy`] member, controlling how unknown attributes are handled. |
|
||||
| `on_unknown_child` | *identifier* | Name of an [`UnknownChildPolicy`] member, controlling how unknown children are handled. |
|
||||
|
||||
Note that the `name` value must be a valid XML element name, without colons.
|
||||
The namespace prefix, if any, is assigned automatically at serialisation time
|
||||
|
|
|
|||
|
|
@ -229,6 +229,44 @@ impl<T: FromXml, E: From<Error>> FromXml for Result<T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Builder which discards an entire child tree without inspecting the
|
||||
/// contents.
|
||||
#[derive(Debug)]
|
||||
pub struct Discard {
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
impl Discard {
|
||||
/// Create a new discarding builder.
|
||||
pub fn new() -> Self {
|
||||
Self { depth: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl FromEventsBuilder for Discard {
|
||||
type Output = ();
|
||||
|
||||
fn feed(&mut self, ev: rxml::Event) -> Result<Option<Self::Output>, Error> {
|
||||
match ev {
|
||||
rxml::Event::StartElement(..) => {
|
||||
self.depth = match self.depth.checked_add(1) {
|
||||
Some(v) => v,
|
||||
None => return Err(Error::Other("maximum XML nesting depth exceeded")),
|
||||
};
|
||||
Ok(None)
|
||||
}
|
||||
rxml::Event::EndElement(..) => match self.depth.checked_sub(1) {
|
||||
None => Ok(Some(())),
|
||||
Some(v) => {
|
||||
self.depth = v;
|
||||
Ok(None)
|
||||
}
|
||||
},
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -323,6 +323,38 @@ impl UnknownAttributePolicy {
|
|||
}
|
||||
}
|
||||
|
||||
/// Control how unknown children are handled.
|
||||
///
|
||||
/// The variants of this enum are referenced in the
|
||||
/// `#[xml(on_unknown_child = ..)]` which can be used on structs and
|
||||
/// enum variants. The specified variant controls how children, which are not
|
||||
/// handled by any member of the compound, are handled during parsing.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
|
||||
pub enum UnknownChildPolicy {
|
||||
/// All unknown children are discarded.
|
||||
Discard,
|
||||
|
||||
/// The first unknown child which is encountered generates a fatal
|
||||
/// parsing error.
|
||||
///
|
||||
/// This is the default policy.
|
||||
#[default]
|
||||
Fail,
|
||||
}
|
||||
|
||||
impl UnknownChildPolicy {
|
||||
#[doc(hidden)]
|
||||
/// Implementation of the policy.
|
||||
///
|
||||
/// This is an internal API and not subject to semver versioning.
|
||||
pub fn apply_policy(&self, msg: &'static str) -> Result<(), self::error::Error> {
|
||||
match self {
|
||||
Self::Fail => Err(self::error::Error::Other(msg)),
|
||||
Self::Discard => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to transform a type implementing [`AsXml`] into another
|
||||
/// type which implements [`FromXml`].
|
||||
pub fn transform<T: FromXml, F: AsXml>(from: F) -> Result<T, self::error::Error> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue