1use crate::types::value::XmlValue;
6use crate::types::XmlTypeCode;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum XPath2ResultType {
13 String,
15 Boolean,
17 Number,
19 NodeSet,
21 Navigator,
23 DateTime,
25 Duration,
27 QName,
29 AnyUri,
31 Other,
33 Any,
35}
36
37pub fn get_value_result_type(value: &XmlValue) -> XPath2ResultType {
39 get_result_type(value.type_code)
40}
41
42pub fn get_result_type(type_code: XmlTypeCode) -> XPath2ResultType {
44 match type_code {
45 XmlTypeCode::String
47 | XmlTypeCode::NormalizedString
48 | XmlTypeCode::Token
49 | XmlTypeCode::Language
50 | XmlTypeCode::NmToken
51 | XmlTypeCode::Name
52 | XmlTypeCode::NCName
53 | XmlTypeCode::Id
54 | XmlTypeCode::IdRef
55 | XmlTypeCode::Entity
56 | XmlTypeCode::UntypedAtomic => XPath2ResultType::String,
57
58 XmlTypeCode::Boolean => XPath2ResultType::Boolean,
60
61 XmlTypeCode::Decimal
63 | XmlTypeCode::Float
64 | XmlTypeCode::Double
65 | XmlTypeCode::Integer
66 | XmlTypeCode::NonPositiveInteger
67 | XmlTypeCode::NegativeInteger
68 | XmlTypeCode::Long
69 | XmlTypeCode::Int
70 | XmlTypeCode::Short
71 | XmlTypeCode::Byte
72 | XmlTypeCode::NonNegativeInteger
73 | XmlTypeCode::UnsignedLong
74 | XmlTypeCode::UnsignedInt
75 | XmlTypeCode::UnsignedShort
76 | XmlTypeCode::UnsignedByte
77 | XmlTypeCode::PositiveInteger => XPath2ResultType::Number,
78
79 XmlTypeCode::DateTime
81 | XmlTypeCode::Date
82 | XmlTypeCode::Time
83 | XmlTypeCode::GYear
84 | XmlTypeCode::GYearMonth
85 | XmlTypeCode::GMonth
86 | XmlTypeCode::GMonthDay
87 | XmlTypeCode::GDay => XPath2ResultType::DateTime,
88
89 XmlTypeCode::Duration | XmlTypeCode::YearMonthDuration | XmlTypeCode::DayTimeDuration => {
91 XPath2ResultType::Duration
92 }
93
94 XmlTypeCode::QName | XmlTypeCode::Notation => XPath2ResultType::QName,
96
97 XmlTypeCode::AnyUri => XPath2ResultType::AnyUri,
99
100 XmlTypeCode::Node
102 | XmlTypeCode::Document
103 | XmlTypeCode::Element
104 | XmlTypeCode::Attribute
105 | XmlTypeCode::Namespace
106 | XmlTypeCode::ProcessingInstruction
107 | XmlTypeCode::Comment
108 | XmlTypeCode::Text => XPath2ResultType::Navigator,
109
110 XmlTypeCode::Item | XmlTypeCode::AnyType | XmlTypeCode::AnySimpleType => {
112 XPath2ResultType::Any
113 }
114
115 _ => XPath2ResultType::Other,
117 }
118}
119
120pub fn is_numeric_type(type_code: XmlTypeCode) -> bool {
122 type_code.is_numeric()
123}
124
125pub fn is_string_type(type_code: XmlTypeCode) -> bool {
127 type_code.is_string_derived() || type_code == XmlTypeCode::UntypedAtomic
128}
129
130pub fn is_datetime_type(type_code: XmlTypeCode) -> bool {
132 matches!(
133 type_code,
134 XmlTypeCode::DateTime
135 | XmlTypeCode::Date
136 | XmlTypeCode::Time
137 | XmlTypeCode::GYear
138 | XmlTypeCode::GYearMonth
139 | XmlTypeCode::GMonth
140 | XmlTypeCode::GMonthDay
141 | XmlTypeCode::GDay
142 )
143}
144
145pub fn is_duration_type(type_code: XmlTypeCode) -> bool {
147 matches!(
148 type_code,
149 XmlTypeCode::Duration | XmlTypeCode::YearMonthDuration | XmlTypeCode::DayTimeDuration
150 )
151}
152
153pub fn is_node_type(type_code: XmlTypeCode) -> bool {
155 type_code.is_node()
156}
157
158pub fn get_base_primitive(type_code: XmlTypeCode) -> XmlTypeCode {
160 match type_code {
161 XmlTypeCode::NormalizedString
163 | XmlTypeCode::Token
164 | XmlTypeCode::Language
165 | XmlTypeCode::NmToken
166 | XmlTypeCode::Name
167 | XmlTypeCode::NCName
168 | XmlTypeCode::Id
169 | XmlTypeCode::IdRef
170 | XmlTypeCode::Entity => XmlTypeCode::String,
171
172 XmlTypeCode::NonPositiveInteger
174 | XmlTypeCode::NegativeInteger
175 | XmlTypeCode::Long
176 | XmlTypeCode::Int
177 | XmlTypeCode::Short
178 | XmlTypeCode::Byte
179 | XmlTypeCode::NonNegativeInteger
180 | XmlTypeCode::UnsignedLong
181 | XmlTypeCode::UnsignedInt
182 | XmlTypeCode::UnsignedShort
183 | XmlTypeCode::UnsignedByte
184 | XmlTypeCode::PositiveInteger => XmlTypeCode::Integer,
185
186 XmlTypeCode::YearMonthDuration | XmlTypeCode::DayTimeDuration => XmlTypeCode::Duration,
188
189 _ => type_code,
191 }
192}
193
194pub fn type_code_to_name(type_code: XmlTypeCode) -> &'static str {
196 match type_code {
197 XmlTypeCode::None => "none",
198 XmlTypeCode::Item => "item()",
199 XmlTypeCode::Node => "node()",
200 XmlTypeCode::Document => "document-node()",
201 XmlTypeCode::Element => "element()",
202 XmlTypeCode::Attribute => "attribute()",
203 XmlTypeCode::Namespace => "namespace-node()",
204 XmlTypeCode::ProcessingInstruction => "processing-instruction()",
205 XmlTypeCode::Comment => "comment()",
206 XmlTypeCode::Text => "text()",
207 XmlTypeCode::AnyType => "xs:anyType",
208 XmlTypeCode::AnySimpleType => "xs:anySimpleType",
209 XmlTypeCode::AnyAtomicType => "xs:anyAtomicType",
210 XmlTypeCode::UntypedAtomic => "xs:untypedAtomic",
211 XmlTypeCode::String => "xs:string",
212 XmlTypeCode::NormalizedString => "xs:normalizedString",
213 XmlTypeCode::Token => "xs:token",
214 XmlTypeCode::Language => "xs:language",
215 XmlTypeCode::NmToken => "xs:NMTOKEN",
216 XmlTypeCode::Name => "xs:Name",
217 XmlTypeCode::NCName => "xs:NCName",
218 XmlTypeCode::Id => "xs:ID",
219 XmlTypeCode::IdRef => "xs:IDREF",
220 XmlTypeCode::Entity => "xs:ENTITY",
221 XmlTypeCode::Boolean => "xs:boolean",
222 XmlTypeCode::Decimal => "xs:decimal",
223 XmlTypeCode::Float => "xs:float",
224 XmlTypeCode::Double => "xs:double",
225 XmlTypeCode::Integer => "xs:integer",
226 XmlTypeCode::NonPositiveInteger => "xs:nonPositiveInteger",
227 XmlTypeCode::NegativeInteger => "xs:negativeInteger",
228 XmlTypeCode::Long => "xs:long",
229 XmlTypeCode::Int => "xs:int",
230 XmlTypeCode::Short => "xs:short",
231 XmlTypeCode::Byte => "xs:byte",
232 XmlTypeCode::NonNegativeInteger => "xs:nonNegativeInteger",
233 XmlTypeCode::UnsignedLong => "xs:unsignedLong",
234 XmlTypeCode::UnsignedInt => "xs:unsignedInt",
235 XmlTypeCode::UnsignedShort => "xs:unsignedShort",
236 XmlTypeCode::UnsignedByte => "xs:unsignedByte",
237 XmlTypeCode::PositiveInteger => "xs:positiveInteger",
238 XmlTypeCode::Duration => "xs:duration",
239 XmlTypeCode::DateTime => "xs:dateTime",
240 XmlTypeCode::Time => "xs:time",
241 XmlTypeCode::Date => "xs:date",
242 XmlTypeCode::GYearMonth => "xs:gYearMonth",
243 XmlTypeCode::GYear => "xs:gYear",
244 XmlTypeCode::GMonthDay => "xs:gMonthDay",
245 XmlTypeCode::GDay => "xs:gDay",
246 XmlTypeCode::GMonth => "xs:gMonth",
247 XmlTypeCode::HexBinary => "xs:hexBinary",
248 XmlTypeCode::Base64Binary => "xs:base64Binary",
249 XmlTypeCode::AnyUri => "xs:anyURI",
250 XmlTypeCode::QName => "xs:QName",
251 XmlTypeCode::Notation => "xs:NOTATION",
252 XmlTypeCode::YearMonthDuration => "xs:yearMonthDuration",
253 XmlTypeCode::DayTimeDuration => "xs:dayTimeDuration",
254 _ => "unknown",
255 }
256}
257
258pub fn name_to_type_code(name: &str) -> Option<XmlTypeCode> {
260 let name = name.strip_prefix("xs:").unwrap_or(name);
262
263 match name {
264 "string" => Some(XmlTypeCode::String),
265 "boolean" => Some(XmlTypeCode::Boolean),
266 "decimal" => Some(XmlTypeCode::Decimal),
267 "float" => Some(XmlTypeCode::Float),
268 "double" => Some(XmlTypeCode::Double),
269 "integer" => Some(XmlTypeCode::Integer),
270 "long" => Some(XmlTypeCode::Long),
271 "int" => Some(XmlTypeCode::Int),
272 "short" => Some(XmlTypeCode::Short),
273 "byte" => Some(XmlTypeCode::Byte),
274 "unsignedLong" => Some(XmlTypeCode::UnsignedLong),
275 "unsignedInt" => Some(XmlTypeCode::UnsignedInt),
276 "unsignedShort" => Some(XmlTypeCode::UnsignedShort),
277 "unsignedByte" => Some(XmlTypeCode::UnsignedByte),
278 "positiveInteger" => Some(XmlTypeCode::PositiveInteger),
279 "nonNegativeInteger" => Some(XmlTypeCode::NonNegativeInteger),
280 "negativeInteger" => Some(XmlTypeCode::NegativeInteger),
281 "nonPositiveInteger" => Some(XmlTypeCode::NonPositiveInteger),
282 "duration" => Some(XmlTypeCode::Duration),
283 "dateTime" => Some(XmlTypeCode::DateTime),
284 "time" => Some(XmlTypeCode::Time),
285 "date" => Some(XmlTypeCode::Date),
286 "gYearMonth" => Some(XmlTypeCode::GYearMonth),
287 "gYear" => Some(XmlTypeCode::GYear),
288 "gMonthDay" => Some(XmlTypeCode::GMonthDay),
289 "gDay" => Some(XmlTypeCode::GDay),
290 "gMonth" => Some(XmlTypeCode::GMonth),
291 "hexBinary" => Some(XmlTypeCode::HexBinary),
292 "base64Binary" => Some(XmlTypeCode::Base64Binary),
293 "anyURI" => Some(XmlTypeCode::AnyUri),
294 "QName" => Some(XmlTypeCode::QName),
295 "NOTATION" => Some(XmlTypeCode::Notation),
296 "normalizedString" => Some(XmlTypeCode::NormalizedString),
297 "token" => Some(XmlTypeCode::Token),
298 "language" => Some(XmlTypeCode::Language),
299 "NMTOKEN" => Some(XmlTypeCode::NmToken),
300 "Name" => Some(XmlTypeCode::Name),
301 "NCName" => Some(XmlTypeCode::NCName),
302 "ID" => Some(XmlTypeCode::Id),
303 "IDREF" => Some(XmlTypeCode::IdRef),
304 "ENTITY" => Some(XmlTypeCode::Entity),
305 "untypedAtomic" => Some(XmlTypeCode::UntypedAtomic),
306 "anyAtomicType" => Some(XmlTypeCode::AnyAtomicType),
307 "yearMonthDuration" => Some(XmlTypeCode::YearMonthDuration),
308 "dayTimeDuration" => Some(XmlTypeCode::DayTimeDuration),
309 _ => None,
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316 use num_bigint::BigInt;
317
318 #[test]
319 fn test_get_result_type() {
320 assert_eq!(
321 get_result_type(XmlTypeCode::String),
322 XPath2ResultType::String
323 );
324 assert_eq!(
325 get_result_type(XmlTypeCode::Boolean),
326 XPath2ResultType::Boolean
327 );
328 assert_eq!(
329 get_result_type(XmlTypeCode::Integer),
330 XPath2ResultType::Number
331 );
332 assert_eq!(
333 get_result_type(XmlTypeCode::DateTime),
334 XPath2ResultType::DateTime
335 );
336 assert_eq!(
337 get_result_type(XmlTypeCode::Duration),
338 XPath2ResultType::Duration
339 );
340 assert_eq!(
341 get_result_type(XmlTypeCode::Element),
342 XPath2ResultType::Navigator
343 );
344 }
345
346 #[test]
347 fn test_get_value_result_type() {
348 let value = XmlValue::string("test");
349 assert_eq!(get_value_result_type(&value), XPath2ResultType::String);
350
351 let value = XmlValue::integer(BigInt::from(42));
352 assert_eq!(get_value_result_type(&value), XPath2ResultType::Number);
353 }
354
355 #[test]
356 fn test_is_numeric_type() {
357 assert!(is_numeric_type(XmlTypeCode::Integer));
358 assert!(is_numeric_type(XmlTypeCode::Decimal));
359 assert!(is_numeric_type(XmlTypeCode::Double));
360 assert!(!is_numeric_type(XmlTypeCode::String));
361 }
362
363 #[test]
364 fn test_type_code_to_name() {
365 assert_eq!(type_code_to_name(XmlTypeCode::String), "xs:string");
366 assert_eq!(type_code_to_name(XmlTypeCode::Integer), "xs:integer");
367 assert_eq!(type_code_to_name(XmlTypeCode::Element), "element()");
368 }
369
370 #[test]
371 fn test_name_to_type_code() {
372 assert_eq!(name_to_type_code("string"), Some(XmlTypeCode::String));
373 assert_eq!(name_to_type_code("xs:integer"), Some(XmlTypeCode::Integer));
374 assert_eq!(name_to_type_code("unknown"), None);
375 }
376
377 #[test]
378 fn test_get_base_primitive() {
379 assert_eq!(get_base_primitive(XmlTypeCode::Long), XmlTypeCode::Integer);
380 assert_eq!(get_base_primitive(XmlTypeCode::Token), XmlTypeCode::String);
381 assert_eq!(get_base_primitive(XmlTypeCode::String), XmlTypeCode::String);
382 }
383}