Skip to main content

xsd/
type.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{DecimalType, DecimalValue, PrimitiveType, PrimitiveValue};
4use core::str::FromStr;
5use phf::phf_map;
6use strum_macros::Display;
7
8#[cfg(feature = "alloc")]
9use ::alloc::{borrow::Cow, format, string::String, vec::Vec};
10
11/// An XSD datatype.
12///
13/// Currently supports the primitive datatypes and the derived `xsd:decimal`
14/// datatypes.
15///
16/// See: <https://www.w3.org/TR/xmlschema-2/#built-in-datatypes>
17#[derive(Clone, Debug, Display, Eq, Hash, Ord, PartialEq, PartialOrd)]
18#[cfg_attr(
19    feature = "borsh",
20    derive(borsh::BorshSerialize, borsh::BorshDeserialize)
21)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub enum Type {
24    Primitive(PrimitiveType),
25
26    Decimal(DecimalType),
27
28    #[cfg(feature = "alloc")]
29    Other(String),
30    #[cfg(not(feature = "alloc"))]
31    Other(&'static str),
32}
33
34impl Type {
35    pub fn name(&self) -> &str {
36        use Type::*;
37        match self {
38            Decimal(t) => t.name(),
39            Primitive(t) => t.name(),
40            Other(s) => s.as_ref(),
41        }
42    }
43
44    pub fn curie(&self) -> &str {
45        use Type::*;
46        match self {
47            Decimal(t) => t.curie(),
48            Primitive(t) => t.curie(),
49            Other(s) => s.as_ref(), // FIXME
50        }
51    }
52
53    #[cfg(feature = "alloc")]
54    pub fn iri_string(&self) -> Cow<'_, str> {
55        Cow::Owned(format!("{}{}", crate::BASE_URI, self))
56    }
57
58    pub fn base_type(&self) -> Option<Type> {
59        use Type::*;
60        match self {
61            Decimal(t) => t.base_type().map(Decimal),
62            Primitive(_) => None,
63            Other(_) => None,
64        }
65    }
66
67    #[cfg(feature = "alloc")]
68    pub fn base_types(&self) -> Vec<Type> {
69        use Type::*;
70        match self {
71            Decimal(t) => t.base_types().into_iter().map(Decimal).collect(),
72            Primitive(_) => Vec::new(),
73            Other(_) => Vec::new(),
74        }
75    }
76}
77
78impl FromStr for Type {
79    type Err = (); // TODO
80
81    fn from_str(input: &str) -> Result<Self, Self::Err> {
82        match TYPES.get(input) {
83            Some(&t) => Ok(t.clone()),
84            None => Err(()),
85        }
86    }
87}
88
89impl From<&Type> for Type {
90    fn from(input: &Type) -> Self {
91        input.clone()
92    }
93}
94
95#[cfg(all(feature = "oxrdf", feature = "alloc"))]
96impl From<oxrdf::NamedNode> for Type {
97    fn from(input: oxrdf::NamedNode) -> Self {
98        let input_iri = input.as_str();
99        if let Some(input_name) = input_iri.strip_prefix(crate::BASE_URI) {
100            return Type::from(input_name);
101        }
102        Type::Other(input_iri.into()) // TODO
103    }
104}
105
106#[cfg(feature = "alloc")]
107impl From<&str> for Type {
108    fn from(input: &str) -> Self {
109        match TYPES.get(input) {
110            Some(&t) => t.clone(),
111            None => Type::Other(input.into()),
112        }
113    }
114}
115
116#[cfg(not(feature = "alloc"))]
117impl From<&'static str> for Type {
118    fn from(input: &'static str) -> Self {
119        match TYPES.get(input) {
120            Some(&t) => t.clone(),
121            None => Type::Other(input.into()),
122        }
123    }
124}
125
126impl From<DecimalType> for Type {
127    fn from(input: DecimalType) -> Self {
128        Self::Decimal(input)
129    }
130}
131
132impl From<DecimalValue> for Type {
133    fn from(input: DecimalValue) -> Self {
134        Self::Decimal(input.r#type())
135    }
136}
137
138impl From<PrimitiveType> for Type {
139    fn from(input: PrimitiveType) -> Self {
140        Self::Primitive(input)
141    }
142}
143
144impl From<PrimitiveValue> for Type {
145    fn from(input: PrimitiveValue) -> Self {
146        Self::Primitive(input.r#type())
147    }
148}
149
150/// A PHF map from XSD typenames to datatypes.
151pub static TYPES: phf::Map<&'static str, &'static Type> = phf_map! {
152    "QName" => &QNAME,
153    "anyURI" => &ANY_URI,
154    "base64Binary" => &BASE64_BINARY,
155    "boolean" => &BOOLEAN,
156    "byte" => &BYTE,
157    "date" => &DATE,
158    "dateTime" => &DATE_TIME,
159    "decimal" => &DECIMAL,
160    "double" => &DOUBLE,
161    "duration" => &DURATION,
162    "float" => &FLOAT,
163    "gDay" => &G_DAY,
164    "gMonth" => &G_MONTH,
165    "gMonthDay" => &G_MONTH_DAY,
166    "gYear" => &G_YEAR,
167    "gYearMonth" => &G_YEAR_MONTH,
168    "hexBinary" => &HEX_BINARY,
169    "int" => &INT,
170    "integer" => &INTEGER,
171    "long" => &LONG,
172    "short" => &SHORT,
173    "string" => &STRING,
174    "time" => &TIME,
175};
176
177/// The `xsd:QName` primitive datatype.
178pub const QNAME: Type = Type::Primitive(PrimitiveType::QName);
179
180/// The `xsd:anyURI` primitive datatype.
181pub const ANY_URI: Type = Type::Primitive(PrimitiveType::AnyUri);
182
183/// The `xsd:base64Binary` primitive datatype.
184pub const BASE64_BINARY: Type = Type::Primitive(PrimitiveType::Base64Binary);
185
186/// The `xsd:boolean` primitive datatype.
187pub const BOOLEAN: Type = Type::Primitive(PrimitiveType::Boolean);
188
189/// The `xsd:byte` derived datatype.
190pub const BYTE: Type = Type::Decimal(DecimalType::Byte);
191
192/// The `xsd:date` primitive datatype.
193pub const DATE: Type = Type::Primitive(PrimitiveType::Date);
194
195/// The `xsd:dateTime` primitive datatype.
196pub const DATE_TIME: Type = Type::Primitive(PrimitiveType::DateTime);
197
198/// The `xsd:decimal` primitive datatype.
199pub const DECIMAL: Type = Type::Decimal(DecimalType::Decimal);
200
201/// The `xsd:double` primitive datatype.
202pub const DOUBLE: Type = Type::Primitive(PrimitiveType::Double);
203
204/// The `xsd:duration` primitive datatype.
205pub const DURATION: Type = Type::Primitive(PrimitiveType::Duration);
206
207/// The `xsd:float` primitive datatype.
208pub const FLOAT: Type = Type::Primitive(PrimitiveType::Float);
209
210/// The `xsd:gDay` primitive datatype.
211pub const G_DAY: Type = Type::Primitive(PrimitiveType::GDay);
212
213/// The `xsd:gMonth` primitive datatype.
214pub const G_MONTH: Type = Type::Primitive(PrimitiveType::GMonth);
215
216/// The `xsd:gMonthDay` primitive datatype.
217pub const G_MONTH_DAY: Type = Type::Primitive(PrimitiveType::GMonthDay);
218
219/// The `xsd:gYear` primitive datatype.
220pub const G_YEAR: Type = Type::Primitive(PrimitiveType::GYear);
221
222/// The `xsd:gYearMonth` primitive datatype.
223pub const G_YEAR_MONTH: Type = Type::Primitive(PrimitiveType::GYearMonth);
224
225/// The `xsd:hexBinary` primitive datatype.
226pub const HEX_BINARY: Type = Type::Primitive(PrimitiveType::HexBinary);
227
228/// The `xsd:int` derived datatype.
229pub const INT: Type = Type::Decimal(DecimalType::Int);
230
231/// The `xsd:integer` derived datatype.
232pub const INTEGER: Type = Type::Decimal(DecimalType::Integer);
233
234/// The `xsd:long` derived datatype.
235pub const LONG: Type = Type::Decimal(DecimalType::Long);
236
237/// The `xsd:short` derived datatype.
238pub const SHORT: Type = Type::Decimal(DecimalType::Short);
239
240/// The `xsd:string` primitive datatype.
241pub const STRING: Type = Type::Primitive(PrimitiveType::String);
242
243/// The `xsd:time` primitive datatype.
244pub const TIME: Type = Type::Primitive(PrimitiveType::Time);