-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Try out the approach to reduce the per-type overhead of these methods described in the README:
Currently static-xml-derive
writes explicit generated code.
E.g., with this type:
#[derive(Deserialize, Serialize)]
struct Foo {
known_field: String,
#[static_xml(flatten)]
unknown_fields: xmltree::Element,
}
The Deserialize
macro produces code roughly as follows:
const ELEMENTS: &[ExpandedNameRef; 1] = &[
ExpandedNameRef { local_name: "known_field", namespace: "" },
];
impl Deserialize for Foo {
fn deserialize(element: ElementReader<'_>) -> Result<Self, VisitorError> {
let mut builder = FooVisitor {
known_field: <String as DeserializeField>::init(),
unknown_fields: <XmlTree as DeserializeField>::init(),
};
element.read_to(&mut builder)?;
Self {
known_field: <String as DeserializeField>::finalize(builder.known_field)?,
unknown_fields: <XmlTree as DeserializeField>::finalize(builder.unknown_fields)?,
}
}
}
pub struct FooVisitor {
known_field: <String as DeserializeField>::Builder,
unknown_fields: <xmltree::Element as DeserializeFlatten>::Builder,
}
impl ElementVisitor for FooVisitor {
fn element<'a>(
&mut self,
child: ElementReader<'a>
) -> Result<Option<ElementReader<'a>>, VisitorError> {
match find(&child.expanded_name(), ELEMENTS) {
Some(0usize) => {
::static_xml::de::DeserializeFieldBuilder::element(&mut self.known_field, child)?;
return Ok(None);
}
_ => delegate_element(&mut [&mut self.unknown_fields], child),
}
}
}
I believe this is close to the minimal size with this approach. Next I'd like to experiment with a different approach in which the Visitor
impl is replaced with a table that holds the offset within FooVisitor
of each field, and a pointer to an element
function. The generated code would use unsafe
, but soundness only has to be proved once in the generator, and this seems worthwhile if it can achieve significant code size reduction.
Metadata
Metadata
Assignees
Labels
No labels