xso-proc: start making derive macros for FromXml and IntoXml

For now, these macros only support empty elements. Everything else will
be rejected with a compile-time error.
This commit is contained in:
Jonas Schäfer 2024-06-21 17:53:37 +02:00
commit 0adfd1218b
10 changed files with 662 additions and 1 deletions

50
xso/src/from_xml_doc.md Normal file
View file

@ -0,0 +1,50 @@
# Make a struct or enum parseable from XML
This derives the [`FromXml`] trait on a struct or enum. It is the counterpart
to [`macro@IntoXml`].
## Example
```rust
# use xso::FromXml;
static MY_NAMESPACE: &str = "urn:example";
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = MY_NAMESPACE, name = "foo")]
struct Foo;
let foo: Foo = xso::from_bytes(b"<foo xmlns='urn:example'/>").unwrap();
assert_eq!(foo, Foo);
```
## Attributes
The derive macros need to know which XML namespace and name the elements it
is supposed have. This must be specified via key-value pairs on the type the
derive macro is invoked on. These are specified as Rust attributes. In order
to disambiguate between XML attributes and Rust attributes, we are going to
refer to Rust attributes using the term *meta* instead, which is consistent
with the Rust language reference calling that syntax construct *meta*.
All key-value pairs interpreted by these derive macros must be wrapped in a
`#[xml( ... )]` *meta*. The following keys are defined on structs:
| Key | Value type | Description |
| --- | --- | --- |
| `namespace` | *path* | The path to a `&'static str` which holds the XML namespace to match. |
| `name` | *string literal* | The XML element name to match. |
## Limitations
Supports only empty structs currently. For example, the following will not
work:
```compile_fail
# use xso::FromXml;
# static MY_NAMESPACE: &str = "urn:example";
#[derive(FromXml, Debug, PartialEq)]
#[xml(namespace = MY_NAMESPACE, name = "foo")]
struct Foo {
some_field: String,
}
```

View file

@ -20,13 +20,32 @@ use of this library in parsing XML streams like specified in RFC 6120.
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
pub mod error;
#[cfg(feature = "minidom")]
pub mod minidom_compat;
#[doc(hidden)]
pub mod exports {
#[cfg(feature = "minidom")]
pub use minidom;
pub use rxml;
}
#[doc = include_str!("from_xml_doc.md")]
#[doc(inline)]
#[cfg(feature = "macros")]
pub use xso_proc::FromXml;
/// # Make a struct or enum serialisable to XML
///
/// This derives the [`IntoXml`] trait on a struct or enum. It is the
/// counterpart to [`macro@FromXml`].
///
/// The attributes necessary and available for the derivation to work are
/// documented on [`macro@FromXml`].
#[doc(inline)]
#[cfg(feature = "macros")]
pub use xso_proc::IntoXml;
/// Trait allowing to consume a struct and iterate its contents as
/// serialisable [`rxml::Event`] items.
///
@ -145,6 +164,7 @@ pub fn transform<T: FromXml, F: IntoXml>(from: F) -> Result<T, self::error::Erro
/// Unlike [`transform`] (which can also be used with an element), this
/// function will return the element unharmed if its element header does not
/// match the expectations of `T`.
#[cfg(feature = "minidom")]
pub fn try_from_element<T: FromXml>(
from: minidom::Element,
) -> Result<T, self::error::FromElementError> {