1const XS_NAMESPACE: &str = "http://www.w3.org/2001/XMLSchema";
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize))]
5pub enum Xs {
6 AnyType,
7 AnySimpleType,
8 Error,
9 Untyped,
10 AnyAtomicType,
11 Numeric,
12 String,
13 UntypedAtomic,
14 Boolean,
15 Decimal,
16 NonPositiveInteger,
17 NegativeInteger,
18 NonNegativeInteger,
19 PositiveInteger,
20 Integer,
21 Long,
22 Int,
23 Short,
24 Byte,
25 UnsignedLong,
26 UnsignedInt,
27 UnsignedShort,
28 UnsignedByte,
29 Float,
30 Double,
31 QName,
32 Notation,
33 Duration,
34 YearMonthDuration,
35 DayTimeDuration,
36 Time,
37 GYearMonth,
38 GYear,
39 GMonthDay,
40 GMonth,
41 GDay,
42 Base64Binary,
43 HexBinary,
44 AnyURI,
45 DateTime,
46 DateTimeStamp,
47 Date,
48 NormalizedString,
49 Token,
50 Language,
51 NMTOKEN,
52 Name,
53 NCName,
54 ID,
55 IDREF,
56 ENTITY,
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub struct RustInfo {
61 rust_name: String,
62 as_ref: bool,
63}
64
65impl RustInfo {
66 fn new(rust_name: &str) -> Self {
67 Self {
68 rust_name: rust_name.to_string(),
69 as_ref: false,
70 }
71 }
72
73 fn as_ref(rust_name: &str) -> Self {
74 Self {
75 rust_name: rust_name.to_string(),
76 as_ref: true,
77 }
78 }
79
80 pub fn rust_name(&self) -> &str {
81 &self.rust_name
82 }
83
84 pub fn is_reference(&self) -> bool {
85 self.as_ref
86 }
87}
88
89impl Xs {
90 pub fn by_name(namespace: &str, local_name: &str) -> Option<Self> {
91 if namespace == XS_NAMESPACE {
92 Xs::by_local_name(local_name)
93 } else {
94 None
95 }
96 }
97
98 pub fn by_local_name(local_name: &str) -> Option<Self> {
99 use Xs::*;
100 let xs = match local_name {
101 "anyType" => AnyType,
102 "anySimpleType" => AnySimpleType,
103 "error" => Error,
104 "untyped" => Untyped,
105 "anyAtomicType" => AnyAtomicType,
106 "numeric" => Numeric,
107 "string" => String,
108 "untypedAtomic" => UntypedAtomic,
109 "boolean" => Boolean,
110 "decimal" => Decimal,
111 "nonPositiveInteger" => NonPositiveInteger,
112 "negativeInteger" => NegativeInteger,
113 "nonNegativeInteger" => NonNegativeInteger,
114 "positiveInteger" => PositiveInteger,
115 "integer" => Integer,
116 "long" => Long,
117 "int" => Int,
118 "short" => Short,
119 "byte" => Byte,
120 "unsignedLong" => UnsignedLong,
121 "unsignedInt" => UnsignedInt,
122 "unsignedShort" => UnsignedShort,
123 "unsignedByte" => UnsignedByte,
124 "float" => Float,
125 "double" => Double,
126 "QName" => QName,
127 "NOTATION" => Notation,
128 "duration" => Duration,
129 "yearMonthDuration" => YearMonthDuration,
130 "dayTimeDuration" => DayTimeDuration,
131 "time" => Time,
132 "gYearMonth" => GYearMonth,
133 "gYear" => GYear,
134 "gMonthDay" => GMonthDay,
135 "gMonth" => GMonth,
136 "gDay" => GDay,
137 "base64Binary" => Base64Binary,
138 "hexBinary" => HexBinary,
139 "anyURI" => AnyURI,
140 "dateTime" => DateTime,
141 "dateTimeStamp" => DateTimeStamp,
142 "date" => Date,
143 "normalizedString" => NormalizedString,
144 "token" => Token,
145 "language" => Language,
146 "NMTOKEN" => NMTOKEN,
147 "Name" => Name,
148 "NCName" => NCName,
149 "ID" => ID,
150 "IDREF" => IDREF,
151 "ENTITY" => ENTITY,
152 _ => return None,
153 };
154 Some(xs)
155 }
156
157 pub fn namespace() -> &'static str {
158 XS_NAMESPACE
159 }
160
161 pub fn local_name(&self) -> &str {
162 use Xs::*;
163 match self {
164 AnyType => "anyType",
165 AnySimpleType => "anySimpleType",
166 Error => "error",
167 Untyped => "untyped",
168 AnyAtomicType => "anyAtomicType",
169 Numeric => "numeric",
170 String => "string",
171 UntypedAtomic => "untypedAtomic",
172 Boolean => "boolean",
173 Decimal => "decimal",
174 NonPositiveInteger => "nonPositiveInteger",
175 NegativeInteger => "negativeInteger",
176 NonNegativeInteger => "nonNegativeInteger",
177 PositiveInteger => "positiveInteger",
178 Integer => "integer",
179 Long => "long",
180 Int => "int",
181 Short => "short",
182 Byte => "byte",
183 UnsignedLong => "unsignedLong",
184 UnsignedInt => "unsignedInt",
185 UnsignedShort => "unsignedShort",
186 UnsignedByte => "unsignedByte",
187 Float => "float",
188 Double => "double",
189 QName => "QName",
190 Notation => "NOTATION",
191 Duration => "duration",
192 YearMonthDuration => "yearMonthDuration",
193 DayTimeDuration => "dayTimeDuration",
194 Time => "time",
195 GYearMonth => "gYearMonth",
196 GYear => "gYear",
197 GMonthDay => "gMonthDay",
198 GMonth => "gMonth",
199 GDay => "gDay",
200 Base64Binary => "base64Binary",
201 HexBinary => "hexBinary",
202 AnyURI => "anyURI",
203 DateTime => "dateTime",
204 DateTimeStamp => "dateTimeStamp",
205 Date => "date",
206 NormalizedString => "normalizedString",
207 Token => "token",
208 Language => "language",
209 NMTOKEN => "NMTOKEN",
210 Name => "Name",
211 NCName => "NCName",
212 ID => "ID",
213 IDREF => "IDREF",
214 ENTITY => "ENTITY",
215 }
216 }
217
218 pub fn parent(&self) -> Option<Xs> {
219 use Xs::*;
220 match self {
221 AnyType => None,
222 AnySimpleType => Some(AnyType),
223 Error => None,
224 Untyped => Some(AnyType),
225 AnyAtomicType => Some(AnySimpleType),
226 UntypedAtomic => Some(AnyAtomicType),
227 Numeric => Some(AnySimpleType),
228 String => Some(AnyAtomicType),
229 Boolean => Some(AnyAtomicType),
230 Float => Some(AnyAtomicType),
231 Double => Some(AnyAtomicType),
232 Decimal => Some(AnyAtomicType),
233 Integer => Some(Decimal),
234 NonPositiveInteger => Some(Integer),
235 NegativeInteger => Some(NonPositiveInteger),
236 Long => Some(Integer),
237 Int => Some(Long),
238 Short => Some(Int),
239 Byte => Some(Short),
240 NonNegativeInteger => Some(Integer),
241 PositiveInteger => Some(NonNegativeInteger),
242 UnsignedLong => Some(NonNegativeInteger),
243 UnsignedInt => Some(UnsignedLong),
244 UnsignedShort => Some(UnsignedInt),
245 UnsignedByte => Some(UnsignedShort),
246 QName => Some(AnyAtomicType),
247 Notation => Some(AnyAtomicType),
248 Duration => Some(AnyAtomicType),
249 YearMonthDuration => Some(Duration),
250 DayTimeDuration => Some(Duration),
251 Time => Some(AnyAtomicType),
252 GYearMonth => Some(AnyAtomicType),
253 GYear => Some(AnyAtomicType),
254 GMonthDay => Some(AnyAtomicType),
255 GMonth => Some(AnyAtomicType),
256 GDay => Some(AnyAtomicType),
257 Base64Binary => Some(AnyAtomicType),
258 HexBinary => Some(AnyAtomicType),
259 AnyURI => Some(AnyAtomicType),
260 DateTime => Some(AnyAtomicType),
261 DateTimeStamp => Some(DateTime),
262 Date => Some(AnyAtomicType),
263 NormalizedString => Some(String),
264 Token => Some(NormalizedString),
265 Language => Some(Token),
266 NMTOKEN => Some(Token),
267 Name => Some(Token),
268 NCName => Some(Name),
269 ID => Some(NCName),
270 IDREF => Some(NCName),
271 ENTITY => Some(NCName),
272 }
273 }
274
275 #[inline]
276 pub fn derives_from(&self, other: Xs) -> bool {
277 if self == &other {
278 return true;
279 }
280 let mut xs = *self;
281 while let Some(parent) = xs.parent() {
282 if parent == other {
283 return true;
284 }
285 xs = parent;
286 }
287 false
288 }
289
290 #[inline]
291 pub fn matches(&self, other: Xs) -> bool {
292 if other != Xs::Numeric {
293 return self == &other;
294 }
295 self.derives_from(Xs::Double)
296 || self.derives_from(Xs::Float)
297 || self.derives_from(Xs::Decimal)
298 }
299
300 pub fn rust_info(&self) -> Option<RustInfo> {
301 use Xs::*;
302 match self {
303 AnyType => None,
304 AnySimpleType => None,
305 Error => None,
306 Untyped => None,
307 AnyAtomicType => None,
308 UntypedAtomic => Some(RustInfo::as_ref("String")),
309 Numeric => None,
310 String => Some(RustInfo::as_ref("String")),
311 Float => Some(RustInfo::new("f32")),
312 Double => Some(RustInfo::new("f64")),
313 Decimal => Some(RustInfo::new("rust_decimal::Decimal")),
314 Integer => Some(RustInfo::new("ibig::IBig")),
315 Duration => Some(RustInfo::new("crate::atomic::Duration")),
316 YearMonthDuration => Some(RustInfo::new("crate::atomic::YearMonthDuration")),
317 DayTimeDuration => Some(RustInfo::new("chrono::Duration")),
318 DateTime => Some(RustInfo::new("crate::atomic::NaiveDateTimeWithOffset")),
319 DateTimeStamp => Some(RustInfo::new("chrono::DateTime<chrono::FixedOffset>>")),
320 Time => Some(RustInfo::new("crate::atomic::NaiveTimeWithOffset")),
321 Date => Some(RustInfo::new("crate::atomic::NaiveDateWithOffset")),
322 GYearMonth => Some(RustInfo::new("crate::atomic::GYearMonth")),
323 GYear => Some(RustInfo::new("crate::atomic::GYear")),
324 GMonthDay => Some(RustInfo::new("crate::atomic::GMonthDay")),
325 GDay => Some(RustInfo::new("crate::atomic::GDay")),
326 GMonth => Some(RustInfo::new("crate::atomic::GMonth")),
327 Boolean => Some(RustInfo::new("bool")),
328 Base64Binary => Some(RustInfo::as_ref("Vec<u8>")),
329 HexBinary => Some(RustInfo::as_ref("Vec<u8>")),
330 QName => Some(RustInfo::new("xee_xpath_ast::ast::Name")),
331 Notation => None,
332
333 NonPositiveInteger => Some(RustInfo::new("i64")),
335 NegativeInteger => Some(RustInfo::new("i64")),
336 Long => Some(RustInfo::new("i64")),
337 Int => Some(RustInfo::new("i32")),
338 Short => Some(RustInfo::new("i16")),
339 Byte => Some(RustInfo::new("i8")),
340 NonNegativeInteger => Some(RustInfo::new("u64")),
341 PositiveInteger => Some(RustInfo::new("u64")),
342 UnsignedLong => Some(RustInfo::new("u64")),
343 UnsignedInt => Some(RustInfo::new("u32")),
344 UnsignedShort => Some(RustInfo::new("u16")),
345 UnsignedByte => Some(RustInfo::new("u8")),
346
347 NormalizedString => Some(RustInfo::as_ref("String")),
349 Token => Some(RustInfo::as_ref("String")),
350 Language => Some(RustInfo::as_ref("String")),
351 NMTOKEN => Some(RustInfo::as_ref("String")),
352 Name => Some(RustInfo::as_ref("String")),
353 NCName => Some(RustInfo::as_ref("String")),
354 ID => Some(RustInfo::as_ref("String")),
355 IDREF => Some(RustInfo::as_ref("String")),
356 ENTITY => Some(RustInfo::as_ref("String")),
357 AnyURI => Some(RustInfo::as_ref("String")),
358 }
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use super::*;
365
366 #[test]
367 fn test_derives_from() {
368 assert!(Xs::Integer.derives_from(Xs::Integer));
369 assert!(Xs::Integer.derives_from(Xs::Decimal));
370 assert!(Xs::Integer.derives_from(Xs::AnyAtomicType));
371 assert!(Xs::Integer.derives_from(Xs::AnySimpleType));
372 assert!(Xs::Integer.derives_from(Xs::AnyType));
373 assert!(Xs::Byte.derives_from(Xs::AnyAtomicType));
374 }
375}