xml-schema-derive 0.3.0

Structure generator from XSD source file
Documentation
use crate::xsd::{rust_types_mapping::RustTypesMapping, Implementation, XsdContext};
use proc_macro2::{Ident, TokenStream};

#[derive(Clone, Default, Debug, PartialEq, YaDeserialize)]
#[yaserde(prefix = "xs", namespace = "xs: http://www.w3.org/2001/XMLSchema")]
pub struct List {
  #[yaserde(rename = "itemType", attribute)]
  pub item_type: String,
}

impl Implementation for List {
  fn implement_childs(
    &self,
    _namespace_definition: &TokenStream,
    _prefix: &Option<String>,
    context: &XsdContext,
    struct_name: &Ident,
  ) -> TokenStream {
    let list_type = RustTypesMapping::get(context, &self.item_type);

    quote!(
      #[derive(Clone, Debug, Default, PartialEq)]
      pub struct #struct_name {
        pub items: Vec<#list_type>
      }

      impl yaserde::YaDeserialize for #struct_name {
        fn deserialize<R: std::io::Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
          loop {
            match reader.next_event()? {
              xml::reader::XmlEvent::StartElement{..} => {}
              xml::reader::XmlEvent::Characters(ref text_content) => {
                let items: Vec<#list_type> =
                  text_content
                    .split(' ')
                    .map(|item| item.to_owned())
                    .map(|item| item.parse().unwrap())
                    .collect();

                return Ok(#struct_name {items});
              }
              _ => {break;}
            }
          }

          Err("Unable to parse attribute".to_string())
        }
      }

      impl yaserde::YaSerialize for #struct_name {
        fn serialize<W: std::io::Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
          let content =
            self.items.iter().map(|item| item.to_string()).collect::<Vec<String>>().join(" ");

          let data_event = xml::writer::XmlEvent::characters(&content);
          writer.write(data_event).map_err(|e| e.to_string())?;

          Ok(())
        }

        fn serialize_attributes(&self, mut source_attributes: Vec<xml::attribute::OwnedAttribute>, mut source_namespace: xml::namespace::Namespace) -> Result<(Vec<xml::attribute::OwnedAttribute>, xml::namespace::Namespace), String> {
          Ok((source_attributes, source_namespace))
        }
      }
    )
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use proc_macro2::Span;
  use std::str::FromStr;
  use syn::Ident;

  #[test]
  fn basic_list() {
    let context =
      XsdContext::new(r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"></xs:schema>"#)
        .unwrap();

    let list_type = List {
      item_type: "xs:string".to_string(),
    };

    let struct_name = Ident::new("Parent", Span::call_site());

    let implementation =
      list_type.implement_childs(&TokenStream::new(), &None, &context, &struct_name);

    let expected =
      TokenStream::from_str(r#"
        #[derive(Clone, Debug, Default, PartialEq)]
        pub struct Parent {
          pub items: Vec <String>
        }

        impl yaserde::YaDeserialize for Parent {
          fn deserialize<R: std::io::Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
            loop {
              match reader.next_event()? {
                xml::reader::XmlEvent::StartElement{..} => { }
                xml::reader::XmlEvent::Characters(ref text_content) => {
                  let items: Vec<String> = text_content.split(' ')
                    .map(|item| item.to_owned())
                    .map(|item| item.parse().unwrap())
                    .collect();

                  return Ok(Parent{items});
                }
                _ => { break; }
              }
            }

            Err ("Unable to parse attribute" . to_string ())
          }
        }

        impl yaserde::YaSerialize for Parent {
          fn serialize<W: std::io::Write> (&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
            let content = self
              .items
              .iter()
              .map(|item| item.to_string())
              .collect:: <Vec<String>>().join(" ");

            let data_event = xml::writer::XmlEvent::characters(&content);

            writer.write(data_event).map_err(|e| e.to_string())? ;

            Ok (())
          }

          fn serialize_attributes(
            &self,
            mut source_attributes: Vec<xml::attribute::OwnedAttribute> ,
            mut source_namespace: xml::namespace::Namespace
            ) -> Result<(Vec<xml::attribute::OwnedAttribute> , xml::namespace::Namespace), String> {
            Ok((source_attributes , source_namespace))
          }
        }
      "#).unwrap();

    assert_eq!(implementation.to_string(), expected.to_string());
  }
}