1use std::collections::HashMap;
7
8use once_cell::sync::Lazy;
9
10use super::signature::{FunctionArity, FunctionSignature, FN_2010_NAMESPACE, FN_NAMESPACE};
11use super::FunctionId;
12use crate::types::sequence::SequenceType;
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct FunctionKey {
17 pub namespace: String,
19 pub local_name: String,
21 pub arity: usize,
23}
24
25impl FunctionKey {
26 pub fn new(namespace: impl Into<String>, local_name: impl Into<String>, arity: usize) -> Self {
28 Self {
29 namespace: namespace.into(),
30 local_name: local_name.into(),
31 arity,
32 }
33 }
34}
35
36#[derive(Debug, Clone)]
38pub struct FunctionEntry {
39 pub id: FunctionId,
41 pub signature: FunctionSignature,
43}
44
45impl FunctionEntry {
46 pub fn new(id: FunctionId, signature: FunctionSignature) -> Self {
48 Self { id, signature }
49 }
50}
51
52pub struct FunctionRegistry {
56 entries: Vec<FunctionEntry>,
58 lookup: HashMap<FunctionKey, usize>,
60 variadic_lookup: HashMap<(String, String), usize>,
63}
64
65impl FunctionRegistry {
66 pub fn new() -> Self {
68 Self {
69 entries: Vec::new(),
70 lookup: HashMap::new(),
71 variadic_lookup: HashMap::new(),
72 }
73 }
74
75 pub fn register(&mut self, entry: FunctionEntry) {
77 let index = self.entries.len();
78 let sig = &entry.signature;
79
80 match sig.arity {
82 FunctionArity::Exact(n) => {
83 let key =
84 FunctionKey::new(sig.namespace.to_string(), sig.local_name.to_string(), n);
85 self.lookup.insert(key, index);
86 }
87 FunctionArity::Range(min, max) => {
88 for arity in min..=max {
89 let key = FunctionKey::new(
90 sig.namespace.to_string(),
91 sig.local_name.to_string(),
92 arity,
93 );
94 self.lookup.insert(key, index);
95 }
96 }
97 FunctionArity::Variadic(_) => {
98 self.variadic_lookup.insert(
100 (sig.namespace.to_string(), sig.local_name.to_string()),
101 index,
102 );
103 }
104 }
105
106 self.entries.push(entry);
107 }
108
109 pub fn lookup(
113 &self,
114 namespace: &str,
115 local_name: &str,
116 arity: usize,
117 ) -> Option<&FunctionEntry> {
118 let key = FunctionKey {
120 namespace: namespace.to_string(),
121 local_name: local_name.to_string(),
122 arity,
123 };
124 if let Some(&index) = self.lookup.get(&key) {
125 return Some(&self.entries[index]);
126 }
127
128 let variadic_key = (namespace.to_string(), local_name.to_string());
130 if let Some(&index) = self.variadic_lookup.get(&variadic_key) {
131 let entry = &self.entries[index];
132 if entry.signature.arity.matches(arity) {
133 return Some(entry);
134 }
135 }
136
137 if namespace == FN_2010_NAMESPACE {
139 return self.lookup(FN_NAMESPACE, local_name, arity);
140 }
141
142 None
143 }
144
145 pub fn by_id(&self, id: FunctionId) -> Option<&FunctionEntry> {
147 self.entries.iter().find(|e| e.id == id)
148 }
149
150 pub fn by_id_value(&self, value: u16) -> Option<&FunctionEntry> {
154 self.entries.iter().find(|e| (e.id as u16) == value)
155 }
156
157 pub fn entries(&self) -> &[FunctionEntry] {
159 &self.entries
160 }
161
162 pub fn len(&self) -> usize {
164 self.entries.len()
165 }
166
167 pub fn is_empty(&self) -> bool {
169 self.entries.is_empty()
170 }
171}
172
173impl Default for FunctionRegistry {
174 fn default() -> Self {
175 Self::new()
176 }
177}
178
179pub static FUNCTION_REGISTRY: Lazy<FunctionRegistry> = Lazy::new(|| {
185 let mut registry = FunctionRegistry::new();
186 register_all_functions(&mut registry);
187 registry
188});
189
190fn register_all_functions(registry: &mut FunctionRegistry) {
192 use super::signature::types::*;
194
195 registry.register(FunctionEntry::new(
199 FunctionId::True,
200 FunctionSignature::new(FN_NAMESPACE, "true", vec![], boolean()),
201 ));
202 registry.register(FunctionEntry::new(
203 FunctionId::False,
204 FunctionSignature::new(FN_NAMESPACE, "false", vec![], boolean()),
205 ));
206 registry.register(FunctionEntry::new(
207 FunctionId::Not,
208 FunctionSignature::new(FN_NAMESPACE, "not", vec![item()], boolean()),
209 ));
210 registry.register(FunctionEntry::new(
211 FunctionId::Boolean,
212 FunctionSignature::new(FN_NAMESPACE, "boolean", vec![item()], boolean()),
213 ));
214
215 registry.register(FunctionEntry::new(
219 FunctionId::Position,
220 FunctionSignature::new(FN_NAMESPACE, "position", vec![], integer()),
221 ));
222 registry.register(FunctionEntry::new(
223 FunctionId::Last,
224 FunctionSignature::new(FN_NAMESPACE, "last", vec![], integer()),
225 ));
226
227 registry.register(FunctionEntry::new(
231 FunctionId::Empty,
232 FunctionSignature::new(FN_NAMESPACE, "empty", vec![any()], boolean()),
233 ));
234 registry.register(FunctionEntry::new(
235 FunctionId::Exists,
236 FunctionSignature::new(FN_NAMESPACE, "exists", vec![any()], boolean()),
237 ));
238 registry.register(FunctionEntry::new(
239 FunctionId::Count,
240 FunctionSignature::new(FN_NAMESPACE, "count", vec![any()], integer()),
241 ));
242 registry.register(FunctionEntry::new(
243 FunctionId::Reverse,
244 FunctionSignature::new(FN_NAMESPACE, "reverse", vec![any()], any()),
245 ));
246 registry.register(FunctionEntry::new(
247 FunctionId::ZeroOrOne,
248 FunctionSignature::new(FN_NAMESPACE, "zero-or-one", vec![any()], item_opt()),
249 ));
250 registry.register(FunctionEntry::new(
251 FunctionId::OneOrMore,
252 FunctionSignature::new(FN_NAMESPACE, "one-or-more", vec![any()], any()),
253 ));
254 registry.register(FunctionEntry::new(
255 FunctionId::ExactlyOne,
256 FunctionSignature::new(FN_NAMESPACE, "exactly-one", vec![any()], item()),
257 ));
258 registry.register(FunctionEntry::new(
259 FunctionId::DistinctValues,
260 FunctionSignature::range(
261 FN_NAMESPACE,
262 "distinct-values",
263 1,
264 2,
265 vec![any_atomic_star(), string()],
266 any_atomic_star(),
267 ),
268 ));
269 registry.register(FunctionEntry::new(
270 FunctionId::IndexOf,
271 FunctionSignature::range(
272 FN_NAMESPACE,
273 "index-of",
274 2,
275 3,
276 vec![any_atomic_star(), any_atomic(), string()],
277 integer_star(),
278 ),
279 ));
280 registry.register(FunctionEntry::new(
281 FunctionId::Remove,
282 FunctionSignature::new(FN_NAMESPACE, "remove", vec![any(), integer()], any()),
283 ));
284 registry.register(FunctionEntry::new(
285 FunctionId::InsertBefore,
286 FunctionSignature::new(
287 FN_NAMESPACE,
288 "insert-before",
289 vec![any(), integer(), any()],
290 any(),
291 ),
292 ));
293 registry.register(FunctionEntry::new(
294 FunctionId::Subsequence,
295 FunctionSignature::range(
296 FN_NAMESPACE,
297 "subsequence",
298 2,
299 3,
300 vec![any(), double(), double()],
301 any(),
302 ),
303 ));
304 registry.register(FunctionEntry::new(
305 FunctionId::Unordered,
306 FunctionSignature::new(FN_NAMESPACE, "unordered", vec![any()], any()),
307 ));
308 registry.register(FunctionEntry::new(
309 FunctionId::DeepEqual,
310 FunctionSignature::range(
311 FN_NAMESPACE,
312 "deep-equal",
313 2,
314 3,
315 vec![any(), any(), string()],
316 boolean(),
317 ),
318 ));
319
320 registry.register(FunctionEntry::new(
324 FunctionId::Sum,
325 FunctionSignature::range(
326 FN_NAMESPACE,
327 "sum",
328 1,
329 2,
330 vec![any_atomic_star(), any_atomic_opt()],
331 any_atomic(),
332 ),
333 ));
334 registry.register(FunctionEntry::new(
335 FunctionId::Avg,
336 FunctionSignature::new(
337 FN_NAMESPACE,
338 "avg",
339 vec![any_atomic_star()],
340 any_atomic_opt(),
341 ),
342 ));
343 registry.register(FunctionEntry::new(
344 FunctionId::Min,
345 FunctionSignature::range(
346 FN_NAMESPACE,
347 "min",
348 1,
349 2,
350 vec![any_atomic_star(), string()],
351 any_atomic_opt(),
352 ),
353 ));
354 registry.register(FunctionEntry::new(
355 FunctionId::Max,
356 FunctionSignature::range(
357 FN_NAMESPACE,
358 "max",
359 1,
360 2,
361 vec![any_atomic_star(), string()],
362 any_atomic_opt(),
363 ),
364 ));
365
366 registry.register(FunctionEntry::new(
370 FunctionId::Concat,
371 FunctionSignature::variadic(
372 FN_NAMESPACE,
373 "concat",
374 2,
375 vec![any_atomic_opt(), any_atomic_opt()],
376 string(),
377 ),
378 ));
379 registry.register(FunctionEntry::new(
380 FunctionId::StringJoin,
381 FunctionSignature::new(
382 FN_NAMESPACE,
383 "string-join",
384 vec![string_star(), string()],
385 string(),
386 ),
387 ));
388 registry.register(FunctionEntry::new(
389 FunctionId::Substring,
390 FunctionSignature::range(
391 FN_NAMESPACE,
392 "substring",
393 2,
394 3,
395 vec![string_opt(), double(), double()],
396 string(),
397 ),
398 ));
399 registry.register(FunctionEntry::new(
400 FunctionId::StringLength,
401 FunctionSignature::range(
402 FN_NAMESPACE,
403 "string-length",
404 0,
405 1,
406 vec![string_opt()],
407 integer(),
408 ),
409 ));
410 registry.register(FunctionEntry::new(
411 FunctionId::NormalizeSpace,
412 FunctionSignature::range(
413 FN_NAMESPACE,
414 "normalize-space",
415 0,
416 1,
417 vec![string_opt()],
418 string(),
419 ),
420 ));
421 registry.register(FunctionEntry::new(
422 FunctionId::NormalizeUnicode,
423 FunctionSignature::range(
424 FN_NAMESPACE,
425 "normalize-unicode",
426 1,
427 2,
428 vec![string_opt(), string()],
429 string(),
430 ),
431 ));
432 registry.register(FunctionEntry::new(
433 FunctionId::UpperCase,
434 FunctionSignature::new(FN_NAMESPACE, "upper-case", vec![string_opt()], string()),
435 ));
436 registry.register(FunctionEntry::new(
437 FunctionId::LowerCase,
438 FunctionSignature::new(FN_NAMESPACE, "lower-case", vec![string_opt()], string()),
439 ));
440 registry.register(FunctionEntry::new(
441 FunctionId::Translate,
442 FunctionSignature::new(
443 FN_NAMESPACE,
444 "translate",
445 vec![string_opt(), string(), string()],
446 string(),
447 ),
448 ));
449 registry.register(FunctionEntry::new(
450 FunctionId::EncodeForUri,
451 FunctionSignature::new(FN_NAMESPACE, "encode-for-uri", vec![string_opt()], string()),
452 ));
453 registry.register(FunctionEntry::new(
454 FunctionId::IriToUri,
455 FunctionSignature::new(FN_NAMESPACE, "iri-to-uri", vec![string_opt()], string()),
456 ));
457 registry.register(FunctionEntry::new(
458 FunctionId::EscapeHtmlUri,
459 FunctionSignature::new(
460 FN_NAMESPACE,
461 "escape-html-uri",
462 vec![string_opt()],
463 string(),
464 ),
465 ));
466 registry.register(FunctionEntry::new(
467 FunctionId::Contains,
468 FunctionSignature::range(
469 FN_NAMESPACE,
470 "contains",
471 2,
472 3,
473 vec![string_opt(), string_opt(), string()],
474 boolean(),
475 ),
476 ));
477 registry.register(FunctionEntry::new(
478 FunctionId::StartsWith,
479 FunctionSignature::range(
480 FN_NAMESPACE,
481 "starts-with",
482 2,
483 3,
484 vec![string_opt(), string_opt(), string()],
485 boolean(),
486 ),
487 ));
488 registry.register(FunctionEntry::new(
489 FunctionId::EndsWith,
490 FunctionSignature::range(
491 FN_NAMESPACE,
492 "ends-with",
493 2,
494 3,
495 vec![string_opt(), string_opt(), string()],
496 boolean(),
497 ),
498 ));
499 registry.register(FunctionEntry::new(
500 FunctionId::SubstringBefore,
501 FunctionSignature::range(
502 FN_NAMESPACE,
503 "substring-before",
504 2,
505 3,
506 vec![string_opt(), string_opt(), string()],
507 string(),
508 ),
509 ));
510 registry.register(FunctionEntry::new(
511 FunctionId::SubstringAfter,
512 FunctionSignature::range(
513 FN_NAMESPACE,
514 "substring-after",
515 2,
516 3,
517 vec![string_opt(), string_opt(), string()],
518 string(),
519 ),
520 ));
521 registry.register(FunctionEntry::new(
522 FunctionId::StringToCodepoints,
523 FunctionSignature::new(
524 FN_NAMESPACE,
525 "string-to-codepoints",
526 vec![string_opt()],
527 integer_star(),
528 ),
529 ));
530 registry.register(FunctionEntry::new(
531 FunctionId::CodepointsToString,
532 FunctionSignature::new(
533 FN_NAMESPACE,
534 "codepoints-to-string",
535 vec![integer_star()],
536 string(),
537 ),
538 ));
539 registry.register(FunctionEntry::new(
540 FunctionId::Compare,
541 FunctionSignature::range(
542 FN_NAMESPACE,
543 "compare",
544 2,
545 3,
546 vec![string_opt(), string_opt(), string()],
547 integer_opt(),
548 ),
549 ));
550 registry.register(FunctionEntry::new(
551 FunctionId::CodepointEqual,
552 FunctionSignature::new(
553 FN_NAMESPACE,
554 "codepoint-equal",
555 vec![string_opt(), string_opt()],
556 SequenceType::optional(crate::types::sequence::ItemType::AtomicType(
557 crate::types::XmlTypeCode::Boolean,
558 )),
559 ),
560 ));
561
562 registry.register(FunctionEntry::new(
566 FunctionId::Abs,
567 FunctionSignature::new(FN_NAMESPACE, "abs", vec![numeric_opt()], numeric_opt()),
568 ));
569 registry.register(FunctionEntry::new(
570 FunctionId::Ceiling,
571 FunctionSignature::new(FN_NAMESPACE, "ceiling", vec![numeric_opt()], numeric_opt()),
572 ));
573 registry.register(FunctionEntry::new(
574 FunctionId::Floor,
575 FunctionSignature::new(FN_NAMESPACE, "floor", vec![numeric_opt()], numeric_opt()),
576 ));
577 registry.register(FunctionEntry::new(
578 FunctionId::Round,
579 FunctionSignature::new(FN_NAMESPACE, "round", vec![numeric_opt()], numeric_opt()),
580 ));
581 registry.register(FunctionEntry::new(
582 FunctionId::RoundHalfToEven,
583 FunctionSignature::range(
584 FN_NAMESPACE,
585 "round-half-to-even",
586 1,
587 2,
588 vec![numeric_opt(), integer()],
589 numeric_opt(),
590 ),
591 ));
592
593 registry.register(FunctionEntry::new(
597 FunctionId::Name,
598 FunctionSignature::range(FN_NAMESPACE, "name", 0, 1, vec![node_opt()], string()),
599 ));
600 registry.register(FunctionEntry::new(
601 FunctionId::LocalName,
602 FunctionSignature::range(FN_NAMESPACE, "local-name", 0, 1, vec![node_opt()], string()),
603 ));
604 registry.register(FunctionEntry::new(
605 FunctionId::NamespaceUri,
606 FunctionSignature::range(
607 FN_NAMESPACE,
608 "namespace-uri",
609 0,
610 1,
611 vec![node_opt()],
612 any_uri(),
613 ),
614 ));
615 registry.register(FunctionEntry::new(
616 FunctionId::NodeName,
617 FunctionSignature::new(FN_NAMESPACE, "node-name", vec![node_opt()], qname_opt()),
618 ));
619 registry.register(FunctionEntry::new(
620 FunctionId::Nilled,
621 FunctionSignature::new(
622 FN_NAMESPACE,
623 "nilled",
624 vec![node_opt()],
625 SequenceType::optional(crate::types::sequence::ItemType::AtomicType(
626 crate::types::XmlTypeCode::Boolean,
627 )),
628 ),
629 ));
630 registry.register(FunctionEntry::new(
631 FunctionId::BaseUri,
632 FunctionSignature::range(
633 FN_NAMESPACE,
634 "base-uri",
635 0,
636 1,
637 vec![node_opt()],
638 any_uri_opt(),
639 ),
640 ));
641 registry.register(FunctionEntry::new(
642 FunctionId::DocumentUri,
643 FunctionSignature::new(
644 FN_NAMESPACE,
645 "document-uri",
646 vec![node_opt()],
647 any_uri_opt(),
648 ),
649 ));
650 registry.register(FunctionEntry::new(
651 FunctionId::Lang,
652 FunctionSignature::range(
653 FN_NAMESPACE,
654 "lang",
655 1,
656 2,
657 vec![string_opt(), node()],
658 boolean(),
659 ),
660 ));
661 registry.register(FunctionEntry::new(
662 FunctionId::Root,
663 FunctionSignature::range(FN_NAMESPACE, "root", 0, 1, vec![node_opt()], node_opt()),
664 ));
665 registry.register(FunctionEntry::new(
666 FunctionId::Id,
667 FunctionSignature::range(
668 FN_NAMESPACE,
669 "id",
670 1,
671 2,
672 vec![string_star(), node()],
673 SequenceType::star(crate::types::sequence::ItemType::AnyNode),
674 ),
675 ));
676 registry.register(FunctionEntry::new(
681 FunctionId::Collection,
682 FunctionSignature::range(
683 FN_NAMESPACE,
684 "collection",
685 0,
686 1,
687 vec![string_opt()],
688 SequenceType::star(crate::types::sequence::ItemType::AnyNode),
689 ),
690 ));
691
692 registry.register(FunctionEntry::new(
696 FunctionId::DateTime,
697 FunctionSignature::new(
698 FN_NAMESPACE,
699 "dateTime",
700 vec![date_opt(), time_opt()],
701 datetime_opt(),
702 ),
703 ));
704 registry.register(FunctionEntry::new(
705 FunctionId::CurrentDateTime,
706 FunctionSignature::new(FN_NAMESPACE, "current-dateTime", vec![], datetime()),
707 ));
708 registry.register(FunctionEntry::new(
709 FunctionId::CurrentDate,
710 FunctionSignature::new(FN_NAMESPACE, "current-date", vec![], date()),
711 ));
712 registry.register(FunctionEntry::new(
713 FunctionId::CurrentTime,
714 FunctionSignature::new(FN_NAMESPACE, "current-time", vec![], time()),
715 ));
716 registry.register(FunctionEntry::new(
717 FunctionId::ImplicitTimezone,
718 FunctionSignature::new(
719 FN_NAMESPACE,
720 "implicit-timezone",
721 vec![],
722 day_time_duration(),
723 ),
724 ));
725
726 registry.register(FunctionEntry::new(
728 FunctionId::YearsFromDuration,
729 FunctionSignature::new(
730 FN_NAMESPACE,
731 "years-from-duration",
732 vec![duration_opt()],
733 integer_opt(),
734 ),
735 ));
736 registry.register(FunctionEntry::new(
737 FunctionId::MonthsFromDuration,
738 FunctionSignature::new(
739 FN_NAMESPACE,
740 "months-from-duration",
741 vec![duration_opt()],
742 integer_opt(),
743 ),
744 ));
745 registry.register(FunctionEntry::new(
746 FunctionId::DaysFromDuration,
747 FunctionSignature::new(
748 FN_NAMESPACE,
749 "days-from-duration",
750 vec![duration_opt()],
751 integer_opt(),
752 ),
753 ));
754 registry.register(FunctionEntry::new(
755 FunctionId::HoursFromDuration,
756 FunctionSignature::new(
757 FN_NAMESPACE,
758 "hours-from-duration",
759 vec![duration_opt()],
760 integer_opt(),
761 ),
762 ));
763 registry.register(FunctionEntry::new(
764 FunctionId::MinutesFromDuration,
765 FunctionSignature::new(
766 FN_NAMESPACE,
767 "minutes-from-duration",
768 vec![duration_opt()],
769 integer_opt(),
770 ),
771 ));
772 registry.register(FunctionEntry::new(
773 FunctionId::SecondsFromDuration,
774 FunctionSignature::new(
775 FN_NAMESPACE,
776 "seconds-from-duration",
777 vec![duration_opt()],
778 SequenceType::optional(crate::types::sequence::ItemType::AtomicType(
779 crate::types::XmlTypeCode::Decimal,
780 )),
781 ),
782 ));
783
784 registry.register(FunctionEntry::new(
786 FunctionId::YearFromDateTime,
787 FunctionSignature::new(
788 FN_NAMESPACE,
789 "year-from-dateTime",
790 vec![datetime_opt()],
791 integer_opt(),
792 ),
793 ));
794 registry.register(FunctionEntry::new(
795 FunctionId::MonthFromDateTime,
796 FunctionSignature::new(
797 FN_NAMESPACE,
798 "month-from-dateTime",
799 vec![datetime_opt()],
800 integer_opt(),
801 ),
802 ));
803 registry.register(FunctionEntry::new(
804 FunctionId::DayFromDateTime,
805 FunctionSignature::new(
806 FN_NAMESPACE,
807 "day-from-dateTime",
808 vec![datetime_opt()],
809 integer_opt(),
810 ),
811 ));
812 registry.register(FunctionEntry::new(
813 FunctionId::HoursFromDateTime,
814 FunctionSignature::new(
815 FN_NAMESPACE,
816 "hours-from-dateTime",
817 vec![datetime_opt()],
818 integer_opt(),
819 ),
820 ));
821 registry.register(FunctionEntry::new(
822 FunctionId::MinutesFromDateTime,
823 FunctionSignature::new(
824 FN_NAMESPACE,
825 "minutes-from-dateTime",
826 vec![datetime_opt()],
827 integer_opt(),
828 ),
829 ));
830 registry.register(FunctionEntry::new(
831 FunctionId::SecondsFromDateTime,
832 FunctionSignature::new(
833 FN_NAMESPACE,
834 "seconds-from-dateTime",
835 vec![datetime_opt()],
836 SequenceType::optional(crate::types::sequence::ItemType::AtomicType(
837 crate::types::XmlTypeCode::Decimal,
838 )),
839 ),
840 ));
841 registry.register(FunctionEntry::new(
842 FunctionId::TimezoneFromDateTime,
843 FunctionSignature::new(
844 FN_NAMESPACE,
845 "timezone-from-dateTime",
846 vec![datetime_opt()],
847 day_time_duration_opt(),
848 ),
849 ));
850
851 registry.register(FunctionEntry::new(
853 FunctionId::YearFromDate,
854 FunctionSignature::new(
855 FN_NAMESPACE,
856 "year-from-date",
857 vec![date_opt()],
858 integer_opt(),
859 ),
860 ));
861 registry.register(FunctionEntry::new(
862 FunctionId::MonthFromDate,
863 FunctionSignature::new(
864 FN_NAMESPACE,
865 "month-from-date",
866 vec![date_opt()],
867 integer_opt(),
868 ),
869 ));
870 registry.register(FunctionEntry::new(
871 FunctionId::DayFromDate,
872 FunctionSignature::new(
873 FN_NAMESPACE,
874 "day-from-date",
875 vec![date_opt()],
876 integer_opt(),
877 ),
878 ));
879 registry.register(FunctionEntry::new(
880 FunctionId::TimezoneFromDate,
881 FunctionSignature::new(
882 FN_NAMESPACE,
883 "timezone-from-date",
884 vec![date_opt()],
885 day_time_duration_opt(),
886 ),
887 ));
888
889 registry.register(FunctionEntry::new(
891 FunctionId::HoursFromTime,
892 FunctionSignature::new(
893 FN_NAMESPACE,
894 "hours-from-time",
895 vec![time_opt()],
896 integer_opt(),
897 ),
898 ));
899 registry.register(FunctionEntry::new(
900 FunctionId::MinutesFromTime,
901 FunctionSignature::new(
902 FN_NAMESPACE,
903 "minutes-from-time",
904 vec![time_opt()],
905 integer_opt(),
906 ),
907 ));
908 registry.register(FunctionEntry::new(
909 FunctionId::SecondsFromTime,
910 FunctionSignature::new(
911 FN_NAMESPACE,
912 "seconds-from-time",
913 vec![time_opt()],
914 SequenceType::optional(crate::types::sequence::ItemType::AtomicType(
915 crate::types::XmlTypeCode::Decimal,
916 )),
917 ),
918 ));
919 registry.register(FunctionEntry::new(
920 FunctionId::TimezoneFromTime,
921 FunctionSignature::new(
922 FN_NAMESPACE,
923 "timezone-from-time",
924 vec![time_opt()],
925 day_time_duration_opt(),
926 ),
927 ));
928
929 registry.register(FunctionEntry::new(
931 FunctionId::AdjustDateTimeToTimezone,
932 FunctionSignature::range(
933 FN_NAMESPACE,
934 "adjust-dateTime-to-timezone",
935 1,
936 2,
937 vec![datetime_opt(), day_time_duration_opt()],
938 datetime_opt(),
939 ),
940 ));
941 registry.register(FunctionEntry::new(
942 FunctionId::AdjustDateToTimezone,
943 FunctionSignature::range(
944 FN_NAMESPACE,
945 "adjust-date-to-timezone",
946 1,
947 2,
948 vec![date_opt(), day_time_duration_opt()],
949 date_opt(),
950 ),
951 ));
952 registry.register(FunctionEntry::new(
953 FunctionId::AdjustTimeToTimezone,
954 FunctionSignature::range(
955 FN_NAMESPACE,
956 "adjust-time-to-timezone",
957 1,
958 2,
959 vec![time_opt(), day_time_duration_opt()],
960 time_opt(),
961 ),
962 ));
963
964 registry.register(FunctionEntry::new(
968 FunctionId::ResolveQName,
969 FunctionSignature::new(
970 FN_NAMESPACE,
971 "resolve-QName",
972 vec![string_opt(), element()],
973 qname_opt(),
974 ),
975 ));
976 registry.register(FunctionEntry::new(
977 FunctionId::QName,
978 FunctionSignature::new(FN_NAMESPACE, "QName", vec![string_opt(), string()], qname()),
979 ));
980 registry.register(FunctionEntry::new(
981 FunctionId::PrefixFromQName,
982 FunctionSignature::new(
983 FN_NAMESPACE,
984 "prefix-from-QName",
985 vec![qname_opt()],
986 string_opt(),
987 ),
988 ));
989 registry.register(FunctionEntry::new(
990 FunctionId::LocalNameFromQName,
991 FunctionSignature::new(
992 FN_NAMESPACE,
993 "local-name-from-QName",
994 vec![qname_opt()],
995 string_opt(),
996 ),
997 ));
998 registry.register(FunctionEntry::new(
999 FunctionId::NamespaceUriFromQName,
1000 FunctionSignature::new(
1001 FN_NAMESPACE,
1002 "namespace-uri-from-QName",
1003 vec![qname_opt()],
1004 any_uri_opt(),
1005 ),
1006 ));
1007 registry.register(FunctionEntry::new(
1008 FunctionId::NamespaceUriForPrefix,
1009 FunctionSignature::new(
1010 FN_NAMESPACE,
1011 "namespace-uri-for-prefix",
1012 vec![string_opt(), element()],
1013 any_uri_opt(),
1014 ),
1015 ));
1016 registry.register(FunctionEntry::new(
1017 FunctionId::InScopePrefixes,
1018 FunctionSignature::new(
1019 FN_NAMESPACE,
1020 "in-scope-prefixes",
1021 vec![element()],
1022 string_star(),
1023 ),
1024 ));
1025
1026 registry.register(FunctionEntry::new(
1030 FunctionId::ResolveUri,
1031 FunctionSignature::range(
1032 FN_NAMESPACE,
1033 "resolve-uri",
1034 1,
1035 2,
1036 vec![string_opt(), string()],
1037 any_uri_opt(),
1038 ),
1039 ));
1040 registry.register(FunctionEntry::new(
1041 FunctionId::StaticBaseUri,
1042 FunctionSignature::new(FN_NAMESPACE, "static-base-uri", vec![], any_uri_opt()),
1043 ));
1044
1045 registry.register(FunctionEntry::new(
1049 FunctionId::Matches,
1050 FunctionSignature::range(
1051 FN_NAMESPACE,
1052 "matches",
1053 2,
1054 3,
1055 vec![string_opt(), string(), string()],
1056 boolean(),
1057 ),
1058 ));
1059 registry.register(FunctionEntry::new(
1060 FunctionId::Replace,
1061 FunctionSignature::range(
1062 FN_NAMESPACE,
1063 "replace",
1064 3,
1065 4,
1066 vec![string_opt(), string(), string(), string()],
1067 string(),
1068 ),
1069 ));
1070 registry.register(FunctionEntry::new(
1071 FunctionId::Tokenize,
1072 FunctionSignature::range(
1073 FN_NAMESPACE,
1074 "tokenize",
1075 2,
1076 3,
1077 vec![string_opt(), string(), string()],
1078 string_star(),
1079 ),
1080 ));
1081
1082 registry.register(FunctionEntry::new(
1086 FunctionId::Trace,
1087 FunctionSignature::range(FN_NAMESPACE, "trace", 1, 2, vec![any(), string()], any()),
1088 ));
1089 registry.register(FunctionEntry::new(
1090 FunctionId::Data,
1091 FunctionSignature::new(FN_NAMESPACE, "data", vec![any()], any_atomic_star()),
1092 ));
1093 registry.register(FunctionEntry::new(
1094 FunctionId::DefaultCollation,
1095 FunctionSignature::new(FN_NAMESPACE, "default-collation", vec![], string()),
1096 ));
1097
1098 registry.register(FunctionEntry::new(
1102 FunctionId::String,
1103 FunctionSignature::range(FN_NAMESPACE, "string", 0, 1, vec![item_opt()], string()),
1104 ));
1105 registry.register(FunctionEntry::new(
1106 FunctionId::Number,
1107 FunctionSignature::range(
1108 FN_NAMESPACE,
1109 "number",
1110 0,
1111 1,
1112 vec![any_atomic_opt()],
1113 double(),
1114 ),
1115 ));
1116}
1117
1118#[cfg(test)]
1119mod tests {
1120 use super::*;
1121
1122 #[test]
1123 fn test_registry_lookup() {
1124 let entry = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "count", 1);
1125 assert!(entry.is_some());
1126 let entry = entry.unwrap();
1127 assert_eq!(entry.id, FunctionId::Count);
1128 }
1129
1130 #[test]
1131 fn test_registry_lookup_not_found() {
1132 let entry = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "nonexistent", 1);
1133 assert!(entry.is_none());
1134 }
1135
1136 #[test]
1137 fn test_registry_lookup_wrong_arity() {
1138 let entry = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "count", 2);
1139 assert!(entry.is_none());
1140 }
1141
1142 #[test]
1143 fn test_registry_lookup_range_arity() {
1144 let entry2 = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "substring", 2);
1146 let entry3 = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "substring", 3);
1147 assert!(entry2.is_some());
1148 assert!(entry3.is_some());
1149 assert_eq!(entry2.unwrap().id, FunctionId::Substring);
1150 assert_eq!(entry3.unwrap().id, FunctionId::Substring);
1151 }
1152
1153 #[test]
1154 fn test_registry_lookup_variadic() {
1155 let entry2 = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "concat", 2);
1157 let entry5 = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "concat", 5);
1158 let entry1 = FUNCTION_REGISTRY.lookup(FN_NAMESPACE, "concat", 1);
1159
1160 assert!(entry2.is_some());
1161 assert!(entry5.is_some());
1162 assert!(entry1.is_none()); assert_eq!(entry2.unwrap().id, FunctionId::Concat);
1165 assert_eq!(entry5.unwrap().id, FunctionId::Concat);
1166 }
1167
1168 #[test]
1169 fn test_registry_2010_namespace_alias() {
1170 let entry = FUNCTION_REGISTRY.lookup(FN_2010_NAMESPACE, "count", 1);
1171 assert!(entry.is_some());
1172 assert_eq!(entry.unwrap().id, FunctionId::Count);
1173 }
1174
1175 #[test]
1176 fn test_registry_by_id() {
1177 let entry = FUNCTION_REGISTRY.by_id(FunctionId::Position);
1178 assert!(entry.is_some());
1179 assert_eq!(entry.unwrap().signature.local_name, "position");
1180 }
1181
1182 #[test]
1183 fn test_registry_size() {
1184 assert!(!FUNCTION_REGISTRY.is_empty());
1186 assert!(FUNCTION_REGISTRY.len() > 50);
1187 }
1188}