xee_schema_type/
xs.rs

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            // integer types; are these correct or should we use ibig everywhere?
334            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            // string types (and AnyURI)
348            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}