xso-proc: add support for string literals for namespaces

Jonas Schรคfer created

Makes it easier to use ad-hoc.

Change summary

parsers/src/util/macro_tests.rs | 14 ++++++++++++++
xso-proc/src/meta.rs            | 33 ++++++++++++++++++++++++++++-----
xso/src/from_xml_doc.md         | 12 ++++--------
3 files changed, 46 insertions(+), 13 deletions(-)

Detailed changes

parsers/src/util/macro_tests.rs ๐Ÿ”—

@@ -169,3 +169,17 @@ fn name_path_roundtrip() {
     };
     roundtrip_full::<NamePath>("<bar xmlns='urn:example:ns1'/>");
 }
+
+#[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::<NamespaceLit>("<baz xmlns='urn:example:ns2'/>");
+}

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<Self> {
+        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)]

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"<foo xmlns='urn:example'/>").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,
 }