Skip to main content

xsd_parser/misc/
qname.rs

1use proc_macro2::{Literal, TokenStream};
2use quote::quote;
3use xsd_parser_types::{misc::Namespace, xml::QName};
4
5use crate::pipeline::{
6    generator::{Context as GeneratorContext, Error, ValueGeneratorMode},
7    renderer::{Context as RendererContext, ValueRendererBox},
8};
9
10/// Generates a default value or constant for the [`QName`](crate::models::schema::QName) type
11/// from the passed `value` and returns it as a [`TokenStream`].
12pub fn default(
13    ctx: &GeneratorContext<'_, '_>,
14    value: &str,
15    mode: ValueGeneratorMode,
16) -> Result<ValueRendererBox, Error> {
17    if mode == ValueGeneratorMode::Literal {
18        return Err(Error::InvalidDefaultValue {
19            ident: ctx.ident.clone(),
20            value: value.into(),
21            mode,
22        });
23    }
24
25    let name = QName::from_bytes(value.as_bytes().to_owned());
26    let ns = name
27        .prefix()
28        .and_then(|prefix| ctx.namespaces()?.get(prefix))
29        .map(|ns| Namespace::new(ns.to_vec()));
30
31    Ok(Box::new(
32        move |ctx: &RendererContext<'_, '_>| -> TokenStream {
33            let qname = ctx.resolve_ident_path("::xsd_parser_types::xml::QName");
34            let namespace = ctx.resolve_ident_path("::xsd_parser_types::misc::Namespace");
35
36            let ns = match &ns {
37                None => quote::quote!(None),
38                Some(x) if *x == Namespace::XS => quote::quote!(Some(#namespace::XS)),
39                Some(x) if *x == Namespace::XSI => quote::quote!(Some(#namespace::XSI)),
40                Some(x) if *x == Namespace::XML => quote::quote!(Some(#namespace::XML)),
41                Some(x) => {
42                    let x = Literal::byte_string(x.as_ref());
43
44                    quote::quote!(Some(#namespace::new_const(#x)))
45                }
46            };
47            let index = match name.index() {
48                Some(index) => quote::quote!(Some(#index)),
49                None => quote::quote!(None),
50            };
51            let raw = Literal::byte_string(name.as_bytes());
52
53            quote!(#qname::new_const(#raw, #index, #ns))
54        },
55    ))
56}