xsd_schema/xpath/functions/
signature.rs1use crate::types::sequence::{ItemType, SequenceType};
7
8pub const FN_NAMESPACE: &str = "http://www.w3.org/2005/xpath-functions";
10
11pub const FN_2010_NAMESPACE: &str = "http://www.w3.org/xpath-functions";
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum FunctionArity {
17 Exact(usize),
19 Variadic(usize),
22 Range(usize, usize),
24}
25
26impl FunctionArity {
27 pub fn matches(&self, count: usize) -> bool {
29 match self {
30 Self::Exact(n) => count == *n,
31 Self::Variadic(min) => count >= *min,
32 Self::Range(min, max) => count >= *min && count <= *max,
33 }
34 }
35
36 pub fn min_args(&self) -> usize {
38 match self {
39 Self::Exact(n) => *n,
40 Self::Variadic(min) => *min,
41 Self::Range(min, _) => *min,
42 }
43 }
44
45 pub fn max_args(&self) -> Option<usize> {
47 match self {
48 Self::Exact(n) => Some(*n),
49 Self::Variadic(_) => None,
50 Self::Range(_, max) => Some(*max),
51 }
52 }
53}
54
55#[derive(Debug, Clone)]
57pub struct FunctionSignature {
58 pub namespace: &'static str,
60 pub local_name: &'static str,
62 pub arity: FunctionArity,
64 pub param_types: Vec<SequenceType>,
66 pub return_type: SequenceType,
68}
69
70impl FunctionSignature {
71 pub fn new(
73 namespace: &'static str,
74 local_name: &'static str,
75 param_types: Vec<SequenceType>,
76 return_type: SequenceType,
77 ) -> Self {
78 let arity = FunctionArity::Exact(param_types.len());
79 Self {
80 namespace,
81 local_name,
82 arity,
83 param_types,
84 return_type,
85 }
86 }
87
88 pub fn variadic(
90 namespace: &'static str,
91 local_name: &'static str,
92 min_args: usize,
93 param_types: Vec<SequenceType>,
94 return_type: SequenceType,
95 ) -> Self {
96 Self {
97 namespace,
98 local_name,
99 arity: FunctionArity::Variadic(min_args),
100 param_types,
101 return_type,
102 }
103 }
104
105 pub fn range(
107 namespace: &'static str,
108 local_name: &'static str,
109 min_args: usize,
110 max_args: usize,
111 param_types: Vec<SequenceType>,
112 return_type: SequenceType,
113 ) -> Self {
114 Self {
115 namespace,
116 local_name,
117 arity: FunctionArity::Range(min_args, max_args),
118 param_types,
119 return_type,
120 }
121 }
122
123 pub fn matches_arity(&self, count: usize) -> bool {
125 self.arity.matches(count)
126 }
127
128 pub fn param_type(&self, index: usize) -> SequenceType {
133 if index < self.param_types.len() {
134 self.param_types[index].clone()
135 } else if !self.param_types.is_empty() {
136 self.param_types.last().unwrap().clone()
138 } else {
139 SequenceType::any()
141 }
142 }
143}
144
145pub fn sig_0(local_name: &'static str, return_type: SequenceType) -> FunctionSignature {
149 FunctionSignature::new(FN_NAMESPACE, local_name, vec![], return_type)
150}
151
152pub fn sig_1(
154 local_name: &'static str,
155 arg1: SequenceType,
156 return_type: SequenceType,
157) -> FunctionSignature {
158 FunctionSignature::new(FN_NAMESPACE, local_name, vec![arg1], return_type)
159}
160
161pub fn sig_2(
163 local_name: &'static str,
164 arg1: SequenceType,
165 arg2: SequenceType,
166 return_type: SequenceType,
167) -> FunctionSignature {
168 FunctionSignature::new(FN_NAMESPACE, local_name, vec![arg1, arg2], return_type)
169}
170
171pub fn sig_3(
173 local_name: &'static str,
174 arg1: SequenceType,
175 arg2: SequenceType,
176 arg3: SequenceType,
177 return_type: SequenceType,
178) -> FunctionSignature {
179 FunctionSignature::new(
180 FN_NAMESPACE,
181 local_name,
182 vec![arg1, arg2, arg3],
183 return_type,
184 )
185}
186
187pub mod types {
189 use super::*;
190
191 pub fn string() -> SequenceType {
193 SequenceType::string()
194 }
195
196 pub fn string_opt() -> SequenceType {
198 SequenceType::string_optional()
199 }
200
201 pub fn string_star() -> SequenceType {
203 SequenceType::star(ItemType::AtomicType(crate::types::XmlTypeCode::String))
204 }
205
206 pub fn boolean() -> SequenceType {
208 SequenceType::boolean()
209 }
210
211 pub fn integer() -> SequenceType {
213 SequenceType::integer()
214 }
215
216 pub fn integer_opt() -> SequenceType {
218 SequenceType::integer_optional()
219 }
220
221 pub fn integer_star() -> SequenceType {
223 SequenceType::star(ItemType::AtomicType(crate::types::XmlTypeCode::Integer))
224 }
225
226 pub fn double() -> SequenceType {
228 SequenceType::double()
229 }
230
231 pub fn double_opt() -> SequenceType {
233 SequenceType::double_optional()
234 }
235
236 pub fn any_atomic() -> SequenceType {
238 SequenceType::any_atomic()
239 }
240
241 pub fn any_atomic_opt() -> SequenceType {
243 SequenceType::any_atomic_optional()
244 }
245
246 pub fn any_atomic_star() -> SequenceType {
248 SequenceType::any_atomic_star()
249 }
250
251 pub fn node() -> SequenceType {
253 SequenceType::node()
254 }
255
256 pub fn node_opt() -> SequenceType {
258 SequenceType::optional(ItemType::AnyNode)
259 }
260
261 pub fn nodes() -> SequenceType {
263 SequenceType::nodes()
264 }
265
266 pub fn item() -> SequenceType {
268 SequenceType::item()
269 }
270
271 pub fn item_opt() -> SequenceType {
273 SequenceType::optional(ItemType::AnyItem)
274 }
275
276 pub fn any() -> SequenceType {
278 SequenceType::any()
279 }
280
281 pub fn empty() -> SequenceType {
283 SequenceType::empty()
284 }
285
286 pub fn qname() -> SequenceType {
288 SequenceType::qname()
289 }
290
291 pub fn qname_opt() -> SequenceType {
293 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::QName))
294 }
295
296 pub fn any_uri() -> SequenceType {
298 SequenceType::any_uri()
299 }
300
301 pub fn any_uri_opt() -> SequenceType {
303 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::AnyUri))
304 }
305
306 pub fn datetime() -> SequenceType {
308 SequenceType::datetime()
309 }
310
311 pub fn datetime_opt() -> SequenceType {
313 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::DateTime))
314 }
315
316 pub fn date() -> SequenceType {
318 SequenceType::date()
319 }
320
321 pub fn date_opt() -> SequenceType {
323 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::Date))
324 }
325
326 pub fn time() -> SequenceType {
328 SequenceType::time()
329 }
330
331 pub fn time_opt() -> SequenceType {
333 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::Time))
334 }
335
336 pub fn duration() -> SequenceType {
338 SequenceType::duration()
339 }
340
341 pub fn duration_opt() -> SequenceType {
343 SequenceType::optional(ItemType::AtomicType(crate::types::XmlTypeCode::Duration))
344 }
345
346 pub fn day_time_duration() -> SequenceType {
348 SequenceType::one(ItemType::AtomicType(
349 crate::types::XmlTypeCode::DayTimeDuration,
350 ))
351 }
352
353 pub fn day_time_duration_opt() -> SequenceType {
355 SequenceType::optional(ItemType::AtomicType(
356 crate::types::XmlTypeCode::DayTimeDuration,
357 ))
358 }
359
360 pub fn element() -> SequenceType {
362 SequenceType::one(ItemType::Element(None, None))
363 }
364
365 pub fn numeric() -> SequenceType {
367 SequenceType::double()
369 }
370
371 pub fn numeric_opt() -> SequenceType {
373 SequenceType::double_optional()
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use super::*;
380
381 #[test]
382 fn test_arity_exact() {
383 let arity = FunctionArity::Exact(2);
384 assert!(arity.matches(2));
385 assert!(!arity.matches(1));
386 assert!(!arity.matches(3));
387 assert_eq!(arity.min_args(), 2);
388 assert_eq!(arity.max_args(), Some(2));
389 }
390
391 #[test]
392 fn test_arity_variadic() {
393 let arity = FunctionArity::Variadic(2);
394 assert!(!arity.matches(1));
395 assert!(arity.matches(2));
396 assert!(arity.matches(10));
397 assert_eq!(arity.min_args(), 2);
398 assert_eq!(arity.max_args(), None);
399 }
400
401 #[test]
402 fn test_arity_range() {
403 let arity = FunctionArity::Range(1, 3);
404 assert!(!arity.matches(0));
405 assert!(arity.matches(1));
406 assert!(arity.matches(2));
407 assert!(arity.matches(3));
408 assert!(!arity.matches(4));
409 assert_eq!(arity.min_args(), 1);
410 assert_eq!(arity.max_args(), Some(3));
411 }
412
413 #[test]
414 fn test_signature_param_type() {
415 let sig = sig_2(
416 "substring",
417 types::string(),
418 types::double(),
419 types::string(),
420 );
421
422 assert_eq!(sig.param_type(0), types::string());
423 assert_eq!(sig.param_type(1), types::double());
424 assert_eq!(sig.param_type(2), types::double());
426 }
427
428 #[test]
429 fn test_signature_matches_arity() {
430 let sig = sig_2("test", types::string(), types::string(), types::string());
431 assert!(!sig.matches_arity(1));
432 assert!(sig.matches_arity(2));
433 assert!(!sig.matches_arity(3));
434 }
435}