diff --git a/parsers/src/util/macro_tests.rs b/parsers/src/util/macro_tests.rs index 5958cc7..51e99b0 100644 --- a/parsers/src/util/macro_tests.rs +++ b/parsers/src/util/macro_tests.rs @@ -169,3 +169,17 @@ fn name_path_roundtrip() { }; roundtrip_full::(""); } + +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = "urn:example:ns2", name = "baz")] +struct NamespaceLit; + +#[test] +fn namespace_lit_roundtrip() { + #[allow(unused_imports)] + use std::{ + option::Option::{None, Some}, + result::Result::{Err, Ok}, + }; + roundtrip_full::(""); +} diff --git a/xso-proc/src/meta.rs b/xso-proc/src/meta.rs index 32de9d6..8a393cc 100644 --- a/xso-proc/src/meta.rs +++ b/xso-proc/src/meta.rs @@ -17,11 +17,34 @@ use syn::{spanned::Spanned, *}; use rxml_validation::NcName; -/// Type alias for a `#[xml(namespace = ..)]` attribute. -/// -/// This may, in the future, be replaced by an enum supporting multiple -/// ways to specify a namespace. -pub(crate) type NamespaceRef = Path; +/// Value for the `#[xml(namespace = ..)]` attribute. +#[derive(Debug)] +pub(crate) enum NamespaceRef { + /// The XML namespace is specified as a string literal. + LitStr(LitStr), + + /// The XML namespace is specified as a path. + Path(Path), +} + +impl syn::parse::Parse for NamespaceRef { + fn parse(input: syn::parse::ParseStream<'_>) -> Result { + if input.peek(syn::LitStr) { + Ok(Self::LitStr(input.parse()?)) + } else { + Ok(Self::Path(input.parse()?)) + } + } +} + +impl quote::ToTokens for NamespaceRef { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Self::LitStr(ref lit) => lit.to_tokens(tokens), + Self::Path(ref path) => path.to_tokens(tokens), + } + } +} /// Value for the `#[xml(name = .. )]` attribute. #[derive(Debug)] diff --git a/xso/src/from_xml_doc.md b/xso/src/from_xml_doc.md index 72ef5e3..3854d04 100644 --- a/xso/src/from_xml_doc.md +++ b/xso/src/from_xml_doc.md @@ -7,10 +7,8 @@ to [`macro@IntoXml`]. ```rust # use xso::FromXml; -static MY_NAMESPACE: &str = "urn:example"; - #[derive(FromXml, Debug, PartialEq)] -#[xml(namespace = MY_NAMESPACE, name = "foo")] +#[xml(namespace = "urn:example", name = "foo")] struct Foo; let foo: Foo = xso::from_bytes(b"").unwrap(); @@ -31,7 +29,7 @@ All key-value pairs interpreted by these derive macros must be wrapped in a | Key | Value type | Description | | --- | --- | --- | -| `namespace` | *path* | The path to a `&'static str` which holds the XML namespace to match. | +| `namespace` | *string literal* or *path* | The XML element namespace to match. If it is a *path*, it must point at a `&'static str`. | | `name` | *string literal* or *path* | The XML element name to match. If it is a *path*, it must point at a `&'static NcNameStr`. | Note that the `name` value must be a valid XML element name, without colons. @@ -40,9 +38,8 @@ and cannot be overridden. The following will thus not compile: ```compile_fail # use xso::FromXml; -# static MY_NAMESPACE: &'static str = "urn:example"; #[derive(FromXml, Debug, PartialEq)] -#[xml(namespace = MY_NAMESPACE, name = "fnord:foo")] // colon not allowed +#[xml(namespace = "urn:example", name = "fnord:foo")] // colon not allowed struct Foo; ``` @@ -53,9 +50,8 @@ work: ```compile_fail # use xso::FromXml; -# static MY_NAMESPACE: &str = "urn:example"; #[derive(FromXml, Debug, PartialEq)] -#[xml(namespace = MY_NAMESPACE, name = "foo")] +#[xml(namespace = "urn:example", name = "foo")] struct Foo { some_field: String, }