xml_schema_derive/xsd/
mod.rs1mod annotation;
2mod attribute;
3mod attribute_group;
4mod complex_content;
5mod complex_type;
6mod element;
7mod extension;
8mod import;
9mod list;
10mod max_occurences;
11mod qualification;
12mod restriction;
13mod rust_types_mapping;
14mod schema;
15mod sequence;
16mod simple_content;
17mod simple_type;
18mod union;
19mod xsd_context;
20
21use heck::ToSnakeCase;
22use proc_macro2::{Ident, TokenStream};
23use std::collections::BTreeMap;
24use std::fs;
25use syn::Visibility;
26use xsd_context::XsdContext;
27use yaserde::de::from_str;
28
29trait Implementation {
30 fn implement(
31 &self,
32 _namespace_definition: &TokenStream,
33 _prefix: &Option<String>,
34 _context: &XsdContext,
35 ) -> TokenStream {
36 unimplemented!()
37 }
38
39 fn implement_childs(
40 &self,
41 _namespace_definition: &TokenStream,
42 _prefix: &Option<String>,
43 _context: &XsdContext,
44 _struct_name: &Ident,
45 ) -> TokenStream {
46 unimplemented!()
47 }
48}
49
50#[derive(Clone, Debug)]
51pub struct Xsd {
52 name: String,
53 vis: Visibility,
54 context: XsdContext,
55 schema: schema::Schema,
56}
57
58impl Xsd {
59 pub fn new(
60 name: String,
61 vis: Visibility,
62 content: &str,
63 module_namespace_mappings: &BTreeMap<String, String>,
64 ) -> Result<Self, String> {
65 let context = XsdContext::new(content)?;
66 let context = context.with_module_namespace_mappings(module_namespace_mappings);
67 let schema: schema::Schema = from_str(content)?;
68
69 Ok(Xsd {
70 name,
71 vis,
72 context,
73 schema,
74 })
75 }
76
77 pub fn new_from_file(
78 name: String,
79 vis: Visibility,
80 source: &str,
81 module_namespace_mappings: &BTreeMap<String, String>,
82 ) -> Result<Self, String> {
83 let content = if source.starts_with("http://") || source.starts_with("https://") {
84 log::info!("Load HTTP schema {}", source);
85 reqwest::blocking::get(source)
86 .map_err(|e| e.to_string())?
87 .text()
88 .map_err(|e| e.to_string())?
89 } else {
90 let path = std::env::current_dir().unwrap();
91 log::info!("The current directory is {}", path.display());
92
93 fs::read_to_string(source).map_err(|e| e.to_string())?
94 };
95
96 let content = if content.as_bytes()[0..3] == [0xef, 0xbb, 0xbf] {
98 content[3..].to_owned()
99 } else {
100 content
101 };
102
103 Xsd::new(name, vis, &content, module_namespace_mappings)
104 }
105
106 pub fn implement(&self, target_prefix: &Option<String>) -> TokenStream {
107 let schema = self
108 .schema
109 .implement(&TokenStream::new(), target_prefix, &self.context);
110
111 let mod_name = format_ident!("{}", self.name.to_snake_case());
112 let vis = &self.vis;
113
114 quote! {
115 mod #mod_name {
116 #schema
117 }
118
119 #vis use #mod_name::*;
120 }
121 }
122}