xml_schema_derive/xsd/
complex_type.rs

1use crate::xsd::{
2  annotation::Annotation, attribute::Attribute, complex_content::ComplexContent,
3  sequence::Sequence, simple_content::SimpleContent, Implementation, XsdContext,
4};
5use heck::ToUpperCamelCase;
6use proc_macro2::{Span, TokenStream};
7use syn::Ident;
8
9#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)]
10#[yaserde(
11  rename = "complexType"
12  prefix = "xs",
13  namespace = "xs: http://www.w3.org/2001/XMLSchema"
14)]
15pub struct ComplexType {
16  #[yaserde(attribute)]
17  pub name: String,
18  #[yaserde(rename = "attribute")]
19  pub attributes: Vec<Attribute>,
20  pub sequence: Option<Sequence>,
21  #[yaserde(rename = "simpleContent")]
22  pub simple_content: Option<SimpleContent>,
23  #[yaserde(rename = "complexContent")]
24  pub complex_content: Option<ComplexContent>,
25  #[yaserde(rename = "annotation")]
26  pub annotation: Option<Annotation>,
27}
28
29impl Implementation for ComplexType {
30  fn implement(
31    &self,
32    namespace_definition: &TokenStream,
33    prefix: &Option<String>,
34    context: &XsdContext,
35  ) -> TokenStream {
36    let struct_name = Ident::new(
37      &self.name.replace('.', "_").to_upper_camel_case(),
38      Span::call_site(),
39    );
40    log::info!("Generate sequence");
41    let sequence = self
42      .sequence
43      .as_ref()
44      .map(|sequence| sequence.implement(namespace_definition, prefix, context))
45      .unwrap_or_default();
46
47    log::info!("Generate simple content");
48    let simple_content = self
49      .simple_content
50      .as_ref()
51      .map(|simple_content| simple_content.implement(namespace_definition, prefix, context))
52      .unwrap_or_default();
53
54    let complex_content = self
55      .complex_content
56      .as_ref()
57      .map(|complex_content| {
58        let complex_content_type = complex_content.get_field_implementation(context, prefix);
59        quote!(
60          #[yaserde(flatten)]
61          #complex_content_type,
62        )
63      })
64      .unwrap_or_default();
65
66    let attributes: TokenStream = self
67      .attributes
68      .iter()
69      .map(|attribute| attribute.implement(namespace_definition, prefix, context))
70      .collect();
71
72    let sub_types_implementation = self
73      .sequence
74      .as_ref()
75      .map(|sequence| sequence.get_sub_types_implementation(context, namespace_definition, prefix))
76      .unwrap_or_default();
77
78    let docs = self
79      .annotation
80      .as_ref()
81      .map(|annotation| annotation.implement(namespace_definition, prefix, context))
82      .unwrap_or_default();
83
84    quote! {
85      #docs
86
87      #[derive(Clone, Debug, Default, PartialEq, yaserde_derive::YaDeserialize, yaserde_derive::YaSerialize)]
88      #namespace_definition
89      pub struct #struct_name {
90        #sequence
91        #simple_content
92        #complex_content
93        #attributes
94      }
95
96      #sub_types_implementation
97    }
98  }
99}
100
101impl ComplexType {
102  pub fn get_field_implementation(
103    &self,
104    context: &XsdContext,
105    prefix: &Option<String>,
106  ) -> TokenStream {
107    if self.sequence.is_some() {
108      self
109        .sequence
110        .as_ref()
111        .map(|sequence| sequence.get_field_implementation(context, prefix))
112        .unwrap_or_default()
113    } else {
114      self
115        .simple_content
116        .as_ref()
117        .map(|simple_content| simple_content.get_field_implementation(context, prefix))
118        .unwrap_or_default()
119    }
120  }
121
122  pub fn get_integrated_implementation(&self, parent_name: &str) -> TokenStream {
123    if self.simple_content.is_some() {
124      return quote!(String);
125    }
126
127    if self.sequence.is_some() {
128      let list_wrapper = Ident::new(parent_name, Span::call_site());
129      return quote!(#list_wrapper);
130    }
131
132    quote!(String)
133  }
134}