1use xee_schema_type::Xs;
6use xee_xpath_ast::ast;
7use xee_xpath_ast::parse_sequence_type;
8use xee_xpath_ast::Namespaces;
9use xee_xpath_type::TypeInfo;
10use xot::Xot;
11
12use crate::atomic;
13use crate::context;
14use crate::error;
15use crate::function;
16use crate::xml;
17
18use super::core::Sequence;
19use super::item::Item;
20use super::iter::one;
21use super::iter::option;
22
23impl Sequence {
24 pub fn matches_type<'a>(
26 &self,
27 s: &str,
28 xot: &Xot,
29 get_signature: &impl Fn(&function::Function) -> &'a function::Signature,
30 ) -> error::Result<bool> {
31 let namespaces = Namespaces::default();
32 let sequence_type = parse_sequence_type(s, &namespaces)?;
33 if self
34 .clone()
35 .sequence_type_matching(&sequence_type, xot, get_signature)
36 .is_ok()
37 {
38 Ok(true)
39 } else {
40 Ok(false)
41 }
42 }
43
44 pub(crate) fn sequence_type_matching<'a>(
46 self,
47 sequence_type: &ast::SequenceType,
48 xot: &Xot,
49 get_signature: &impl Fn(&function::Function) -> &'a function::Signature,
50 ) -> error::Result<Self> {
51 self.sequence_type_matching_convert(
52 sequence_type,
53 &|atomic, _| Ok(atomic),
54 &|function_test, item| item.function_type_matching(function_test, &get_signature),
55 xot,
56 )
57 }
58
59 pub(crate) fn sequence_type_matching_function_conversion<'a>(
61 self,
62 sequence_type: &ast::SequenceType,
63 context: &'a context::StaticContext,
64 xot: &Xot,
65 get_signature: &impl Fn(&function::Function) -> &'a function::Signature,
66 ) -> error::Result<Self> {
67 self.sequence_type_matching_convert(
68 sequence_type,
69 &|atomic, xs| Self::cast_or_promote_atomic(atomic, xs, context),
70 &|function_test, item| item.function_arity_matching(function_test, &get_signature),
71 xot,
72 )
73 }
74
75 fn cast_or_promote_atomic(
76 atom: atomic::Atomic,
77 xs: Xs,
78 context: &context::StaticContext,
79 ) -> error::Result<atomic::Atomic> {
80 let atom = if matches!(atom, atomic::Atomic::Untyped(_)) {
81 match xs {
82 Xs::QName | Xs::Notation => {
86 return Err(error::Error::XPTY0117);
87 }
88 _ => atom.cast_to_schema_type(xs, context)?,
89 }
90 } else {
91 atom
92 };
93 atom.type_promote(xs)
94 }
95
96 fn sequence_type_matching_convert(
97 self,
98 t: &ast::SequenceType,
99 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
100 check_function: &impl Fn(&ast::FunctionTest, &Item) -> error::Result<()>,
101 xot: &Xot,
102 ) -> error::Result<Self> {
103 match t {
104 ast::SequenceType::Empty => {
105 if self.is_empty() {
106 Ok(self)
107 } else {
108 Err(error::Error::XPTY0004)
109 }
110 }
111 ast::SequenceType::Item(occurrence_item) => self.occurrence_item_matching(
112 occurrence_item,
113 cast_or_promote_atomic,
114 check_function,
115 xot,
116 ),
117 }
118 }
119
120 fn occurrence_item_matching(
121 self,
122 occurrence_item: &ast::Item,
123 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
124 check_function: &impl Fn(&ast::FunctionTest, &Item) -> error::Result<()>,
125 xot: &Xot,
126 ) -> error::Result<Self> {
127 match &occurrence_item.item_type {
128 ast::ItemType::AtomicOrUnionType(xs) => self.atomic_occurrence_item_matching(
129 occurrence_item,
130 cast_or_promote_atomic,
131 *xs,
132 xot,
133 ),
134 _ => self.non_atomic_occurrence_item_matching(
135 occurrence_item,
136 cast_or_promote_atomic,
137 check_function,
138 xot,
139 ),
140 }
141 }
142
143 fn non_atomic_occurrence_item_matching(
147 self,
148 occurrence_item: &ast::Item,
149 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
150 check_function: &impl Fn(&ast::FunctionTest, &Item) -> error::Result<()>,
151 xot: &Xot,
152 ) -> error::Result<Self> {
153 match occurrence_item.occurrence {
154 ast::Occurrence::One => {
155 let one = one(self.iter())?;
156 one.non_atomic_item_type_matching(
157 &occurrence_item.item_type,
158 cast_or_promote_atomic,
159 check_function,
160 xot,
161 )?;
162 }
163 ast::Occurrence::Option => {
164 let option = option(self.iter())?;
165 if let Some(item) = option {
166 item.non_atomic_item_type_matching(
167 &occurrence_item.item_type,
168 cast_or_promote_atomic,
169 check_function,
170 xot,
171 )?;
172 }
173 }
174 ast::Occurrence::Many => {
175 match occurrence_item.item_type {
176 ast::ItemType::Item => {
177 }
180 _ => {
181 for item in self.iter() {
182 item.non_atomic_item_type_matching(
183 &occurrence_item.item_type,
184 cast_or_promote_atomic,
185 check_function,
186 xot,
187 )?;
188 }
189 }
190 }
191 }
192 ast::Occurrence::NonEmpty => {
193 if self.is_empty() {
194 return Err(error::Error::XPTY0004);
195 }
196 match occurrence_item.item_type {
197 ast::ItemType::Item => {
198 }
201 _ => {
202 for item in self.iter() {
203 item.non_atomic_item_type_matching(
204 &occurrence_item.item_type,
205 cast_or_promote_atomic,
206 check_function,
207 xot,
208 )?;
209 }
210 }
211 }
212 }
213 }
214 Ok(self)
215 }
216
217 fn atomic_occurrence_item_matching(
218 self,
219 occurrence_item: &ast::Item,
220 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
221 xs: Xs,
222 xot: &Xot,
223 ) -> error::Result<Self> {
224 match occurrence_item.occurrence {
225 ast::Occurrence::One => {
226 let one = one(self.atomized(xot))?;
227 let atom = one?.atomic_type_matching(xs, cast_or_promote_atomic)?;
228 Ok(atom.into())
229 }
230 ast::Occurrence::Option => {
231 let option = option(self.atomized(xot))?;
232 if let Some(atom) = option {
233 let atom = atom?.atomic_type_matching(xs, cast_or_promote_atomic)?;
234 Ok(atom.into())
235 } else {
236 Ok(self)
237 }
238 }
239 ast::Occurrence::Many => {
240 let mut atoms = Vec::with_capacity(self.len());
241 for atom in self.atomized(xot) {
242 atoms.push(atom?.atomic_type_matching(xs, cast_or_promote_atomic)?);
243 }
244 Ok(atoms.into())
245 }
246 ast::Occurrence::NonEmpty => {
247 if self.is_empty() {
248 return Err(error::Error::XPTY0004);
249 }
250 let mut atoms = Vec::with_capacity(self.len());
251 for atom in self.atomized(xot) {
252 atoms.push(atom?.atomic_type_matching(xs, cast_or_promote_atomic)?);
253 }
254 Ok(atoms.into())
255 }
256 }
257 }
258}
259
260impl Item {
261 pub(crate) fn non_atomic_item_type_matching(
262 self,
263 item_type: &ast::ItemType,
264 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
265 check_function: &impl Fn(&ast::FunctionTest, &Item) -> error::Result<()>,
266 xot: &Xot,
267 ) -> error::Result<()> {
268 match item_type {
269 ast::ItemType::Item => {}
270 ast::ItemType::AtomicOrUnionType(_) => {
271 unreachable!()
272 }
273 ast::ItemType::KindTest(kind_test) => {
274 self.kind_test_matching(kind_test, xot)?;
275 }
276 ast::ItemType::FunctionTest(function_test) => {
277 check_function(function_test, &self)?;
278 }
279 ast::ItemType::MapTest(map_test) => match map_test {
280 ast::MapTest::AnyMapTest => {
281 if !self.is_map() {
282 return Err(error::Error::XPTY0004);
283 }
284 }
285 ast::MapTest::TypedMapTest(typed_map_test) => {
286 let map = self.to_map()?;
287 for (key, value) in map.entries() {
288 key.clone().atomic_type_matching(
289 typed_map_test.key_type,
290 cast_or_promote_atomic,
291 )?;
292 value.clone().sequence_type_matching_convert(
293 &typed_map_test.value_type,
294 cast_or_promote_atomic,
295 check_function,
296 xot,
297 )?;
298 }
299 }
300 },
301 ast::ItemType::ArrayTest(array_test) => match array_test {
302 ast::ArrayTest::AnyArrayTest => {
303 if !self.is_array() {
304 return Err(error::Error::XPTY0004);
305 }
306 }
307 ast::ArrayTest::TypedArrayTest(typed_array_test) => {
308 let array = self.to_array()?;
309 for sequence in array.iter() {
310 sequence.clone().sequence_type_matching_convert(
311 &typed_array_test.item_type,
312 cast_or_promote_atomic,
313 check_function,
314 xot,
315 )?;
316 }
317 }
318 },
319 }
320 Ok(())
321 }
322
323 fn kind_test_matching(&self, kind_test: &ast::KindTest, xot: &Xot) -> error::Result<()> {
324 match self {
325 Item::Node(node) => {
326 if xml::kind_test(kind_test, xot, *node) {
327 Ok(())
328 } else {
329 Err(error::Error::XPTY0004)
330 }
331 }
332 Item::Atomic(_) => Err(error::Error::XPTY0004),
333 Item::Function(_) => Err(error::Error::XPTY0004),
334 }
335 }
336
337 pub(crate) fn function_arity_matching<'a>(
338 &self,
339 function_test: &ast::FunctionTest,
340 get_signature: &impl Fn(&function::Function) -> &'a function::Signature,
341 ) -> error::Result<()> {
342 match function_test {
343 ast::FunctionTest::AnyFunctionTest => {
344 self.to_function()?;
345 Ok(())
346 }
347 ast::FunctionTest::TypedFunctionTest(typed_function_test) => {
348 let function = self.to_function()?;
349 let signature = get_signature(&function);
350 if signature.arity() == typed_function_test.parameter_types.len() {
351 Ok(())
352 } else {
353 Err(error::Error::XPTY0004)
354 }
355 }
356 }
357 }
358
359 pub(crate) fn function_type_matching<'a>(
360 &self,
361 function_test: &ast::FunctionTest,
362 get_signature: &impl Fn(&function::Function) -> &'a function::Signature,
363 ) -> error::Result<()> {
364 match function_test {
365 ast::FunctionTest::AnyFunctionTest => {
366 self.to_function()?;
367 Ok(())
368 }
369 ast::FunctionTest::TypedFunctionTest(typed_function_test) => {
370 let function = self.to_function()?;
371 let signature = get_signature(&function);
372 if signature.arity() != typed_function_test.parameter_types.len() {
373 return Err(error::Error::XPTY0004);
374 }
375 if Self::function_type_matching_helper(typed_function_test, signature) {
376 Ok(())
377 } else {
378 Err(error::Error::XPTY0004)
379 }
380 }
381 }
382 }
383
384 fn function_type_matching_helper(
385 function_test: &ast::TypedFunctionTest,
386 signature: &function::Signature,
387 ) -> bool {
388 let default_sequence_type = Self::default_sequence_type();
389 let function_return_type = signature.return_type().unwrap_or(&default_sequence_type);
390 if !function_return_type.subtype(&function_test.return_type) {
392 return false;
393 }
394
395 for (function_parameter, test_parameter) in signature
396 .parameter_types()
397 .iter()
398 .zip(&function_test.parameter_types)
399 {
400 let function_parameter = function_parameter
401 .as_ref()
402 .unwrap_or(&default_sequence_type);
403 if !test_parameter.subtype(function_parameter) {
405 return false;
406 }
407 }
408
409 true
410 }
411
412 fn default_sequence_type() -> ast::SequenceType {
413 ast::SequenceType::Item(ast::Item {
414 item_type: ast::ItemType::Item,
415 occurrence: ast::Occurrence::Many,
416 })
417 }
418}
419
420impl atomic::Atomic {
421 fn atomic_type_matching(
422 self,
423 xs: Xs,
424 cast_or_promote_atomic: &impl Fn(atomic::Atomic, Xs) -> error::Result<atomic::Atomic>,
425 ) -> error::Result<Self> {
426 let atom = cast_or_promote_atomic(self, xs)?;
427 let schema_type = atom.schema_type();
428 if schema_type.derives_from(xs) || schema_type.matches(xs) {
429 Ok(atom)
430 } else {
431 Err(error::Error::XPTY0004)
432 }
433 }
434}
435
436#[cfg(test)]
437mod tests {
438
439 use super::*;
440
441 use ibig::ibig;
442 use xee_name::Namespaces;
443 use xee_xpath_ast::parse_sequence_type;
444
445 #[test]
446 fn test_one_integer() {
447 let namespaces = Namespaces::default();
448 let sequence_type = parse_sequence_type("xs:integer", &namespaces).unwrap();
449
450 let right_sequence: Sequence = vec![ibig!(1)].into();
451 let wrong_amount_sequence: Sequence = vec![ibig!(1), ibig!(2)].into();
452 let wrong_type_sequence: Sequence = vec![false].into();
453 let xot = Xot::new();
454
455 let right_result = right_sequence.clone().sequence_type_matching(
456 &sequence_type,
457 &xot,
458 &|_| unreachable!(),
459 );
460 assert_eq!(&right_result.unwrap(), &right_sequence);
461
462 let wrong_amount_result =
463 wrong_amount_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
464 assert_eq!(wrong_amount_result, Err(error::Error::XPTY0004));
465 let wrong_type_result =
466 wrong_type_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
467 assert_eq!(wrong_type_result, Err(error::Error::XPTY0004));
468 }
469
470 #[test]
471 fn test_one_long_matches_integer() {
472 let namespaces = Namespaces::default();
473 let sequence_type = parse_sequence_type("xs:integer", &namespaces).unwrap();
474
475 let right_sequence = Sequence::from(vec![Item::from(1i64)]);
476 let wrong_amount_sequence = Sequence::from(vec![Item::from(1i64), Item::from(1i64)]);
477 let wrong_type_sequence = Sequence::from(vec![Item::from(atomic::Atomic::from(false))]);
478 let xot = Xot::new();
479
480 let right_result = right_sequence.clone().sequence_type_matching(
481 &sequence_type,
482 &xot,
483 &|_| unreachable!(),
484 );
485 assert_eq!(right_result, Ok(right_sequence));
486 let wrong_amount_result =
487 wrong_amount_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
488 assert_eq!(wrong_amount_result, Err(error::Error::XPTY0004));
489 let wrong_type_result =
490 wrong_type_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
491 assert_eq!(wrong_type_result, Err(error::Error::XPTY0004));
492 }
493
494 #[test]
495 fn test_one_any_atomic() {
496 let namespaces = Namespaces::default();
497 let sequence_type = parse_sequence_type("xs:anyAtomicType", &namespaces).unwrap();
498
499 let right_sequence = Sequence::from(vec![Item::from(atomic::Atomic::from(1i64))]);
500 let wrong_amount_sequence =
501 Sequence::from(vec![Item::from(ibig!(1)), Item::from(ibig!(2))]);
502 let right_type_sequence2 = Sequence::from(vec![Item::from(atomic::Atomic::from(false))]);
503 let xot = Xot::new();
504
505 let right_result = right_sequence.clone().sequence_type_matching(
506 &sequence_type,
507 &xot,
508 &|_| unreachable!(),
509 );
510 assert_eq!(right_result, Ok(right_sequence));
511 let wrong_amount_result =
512 wrong_amount_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
513 assert_eq!(wrong_amount_result, Err(error::Error::XPTY0004));
514 let right_type_result2 = right_type_sequence2.clone().sequence_type_matching(
515 &sequence_type,
516 &xot,
517 &|_| unreachable!(),
518 );
519 assert_eq!(right_type_result2, Ok(right_type_sequence2));
520 }
521
522 #[test]
523 fn test_one_item() {
524 let namespaces = Namespaces::default();
525 let sequence_type = parse_sequence_type("item()", &namespaces).unwrap();
526 let mut xot = Xot::new();
527 let root = xot.parse("<doc/>").unwrap();
528 let node = xot.document_element(root).unwrap();
529 let right_sequence = Sequence::from(vec![Item::from(atomic::Atomic::from(1i64))]);
530 let wrong_amount_sequence = Sequence::from(vec![
531 Item::from(atomic::Atomic::from(1i64)),
532 Item::from(atomic::Atomic::from(2i64)),
533 ]);
534 let right_type_sequence2 = Sequence::from(vec![Item::from(node)]);
535
536 let right_result = right_sequence.clone().sequence_type_matching(
537 &sequence_type,
538 &xot,
539 &|_| unreachable!(),
540 );
541 assert_eq!(right_result, Ok(right_sequence));
542
543 let wrong_amount_result =
544 wrong_amount_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
545 assert_eq!(wrong_amount_result, Err(error::Error::XPTY0004));
546 let right_type_result2 = right_type_sequence2.clone().sequence_type_matching(
547 &sequence_type,
548 &xot,
549 &|_| unreachable!(),
550 );
551 assert_eq!(right_type_result2, Ok(right_type_sequence2));
552 }
553
554 #[test]
555 fn test_option_integer() {
556 let namespaces = Namespaces::default();
557 let sequence_type = parse_sequence_type("xs:integer?", &namespaces).unwrap();
558
559 let right_sequence = Sequence::from(vec![Item::from(atomic::Atomic::from(ibig!(1)))]);
560 let wrong_amount_sequence =
561 Sequence::from(vec![Item::from(ibig!(1)), Item::from(ibig!(2))]);
562 let right_empty_sequence = Sequence::default();
563 let xot = Xot::new();
564
565 let right_result = right_sequence.clone().sequence_type_matching(
566 &sequence_type,
567 &xot,
568 &|_| unreachable!(),
569 );
570 assert_eq!(right_result, Ok(right_sequence));
571 let wrong_amount_result =
572 wrong_amount_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
573 assert_eq!(wrong_amount_result, Err(error::Error::XPTY0004));
574 let right_empty_result = right_empty_sequence.clone().sequence_type_matching(
575 &sequence_type,
576 &xot,
577 &|_| unreachable!(),
578 );
579 assert_eq!(right_empty_result, Ok(right_empty_sequence));
580 }
581
582 #[test]
583 fn test_many_integer() {
584 let namespaces = Namespaces::default();
585 let sequence_type = parse_sequence_type("xs:integer*", &namespaces).unwrap();
586
587 let right_sequence = Sequence::from(vec![Item::from(atomic::Atomic::from(ibig!(1)))]);
588 let right_multi_sequence = Sequence::from(vec![Item::from(ibig!(1)), Item::from(ibig!(2))]);
589 let right_empty_sequence = Sequence::default();
590 let xot = Xot::new();
591
592 let right_result = right_sequence.clone().sequence_type_matching(
593 &sequence_type,
594 &xot,
595 &|_| unreachable!(),
596 );
597 assert_eq!(right_result, Ok(right_sequence));
598
599 let right_multi_result = right_multi_sequence.clone().sequence_type_matching(
600 &sequence_type,
601 &xot,
602 &|_| unreachable!(),
603 );
604 assert_eq!(right_multi_result, Ok(right_multi_sequence));
605
606 let right_empty_result = right_empty_sequence.clone().sequence_type_matching(
607 &sequence_type,
608 &xot,
609 &|_| unreachable!(),
610 );
611 assert_eq!(right_empty_result, Ok(right_empty_sequence));
612 }
613
614 #[test]
615 fn test_many_node() {
616 let namespaces = Namespaces::default();
617 let sequence_type = parse_sequence_type("node()*", &namespaces).unwrap();
618
619 let mut xot = Xot::new();
620 let doc = xot.parse(r#"<doc><a attr="Attr">A</a><b/></doc>"#).unwrap();
621 let doc = xot.document_element(doc).unwrap();
622 let a = xot.first_child(doc).unwrap();
623 let b = xot.next_sibling(a).unwrap();
624 let text = xot.first_child(a).unwrap();
625 let attr = xot
626 .attributes(a)
627 .get_node(xot.name("attr").unwrap())
628 .unwrap();
629
630 let right_sequence = Sequence::from(vec![
631 Item::from(doc),
632 Item::from(a),
633 Item::from(b),
634 Item::from(text),
635 Item::from(attr),
636 ]);
637
638 let wrong_sequence = Sequence::from(vec![Item::from(ibig!(1))]);
639
640 let right_result = right_sequence.clone().sequence_type_matching(
641 &sequence_type,
642 &xot,
643 &|_| unreachable!(),
644 );
645 assert_eq!(right_result, Ok(right_sequence));
646
647 let wrong_result =
648 wrong_sequence.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
649 assert_eq!(wrong_result, Err(error::Error::XPTY0004));
650 }
651
652 #[test]
653 fn test_many_element() {
654 let namespaces = Namespaces::default();
655 let sequence_type = parse_sequence_type("element()*", &namespaces).unwrap();
656
657 let mut xot = Xot::new();
658 let doc = xot.parse(r#"<doc><a attr="Attr">A</a><b/></doc>"#).unwrap();
659 let doc = xot.document_element(doc).unwrap();
660 let a = xot.first_child(doc).unwrap();
661 let b = xot.next_sibling(a).unwrap();
662 let text = xot.first_child(a).unwrap();
663 let attr = xot
664 .attributes(a)
665 .get_node(xot.name("attr").unwrap())
666 .unwrap();
667
668 let right_sequence = Sequence::from(vec![Item::from(doc), Item::from(a), Item::from(b)]);
669
670 let wrong_sequence_text = Sequence::from(vec![Item::from(text)]);
671 let wrong_sequence_attr = Sequence::from(vec![Item::from(attr)]);
672
673 let right_result = right_sequence.clone().sequence_type_matching(
674 &sequence_type,
675 &xot,
676 &|_| unreachable!(),
677 );
678 assert_eq!(right_result, Ok(right_sequence));
679
680 let wrong_result =
681 wrong_sequence_text.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
682 assert_eq!(wrong_result, Err(error::Error::XPTY0004));
683 let wrong_result =
684 wrong_sequence_attr.sequence_type_matching(&sequence_type, &xot, &|_| unreachable!());
685 assert_eq!(wrong_result, Err(error::Error::XPTY0004));
686 }
687
688 #[test]
689 fn test_many_atomized_promote() {
690 let namespaces = Namespaces::default();
691 let sequence_type = parse_sequence_type("xs:double*", &namespaces).unwrap();
692
693 let right_sequence = Sequence::from(vec![Item::from(ibig!(1)), Item::from(ibig!(2))]);
695
696 let static_context = context::StaticContext::default();
697 let xot = Xot::new();
698 let right_result = right_sequence.sequence_type_matching_function_conversion(
699 &sequence_type,
700 &static_context,
701 &xot,
702 &|_| unreachable!(),
703 );
704 assert_eq!(
706 right_result,
707 Ok(Sequence::from(vec![
708 Item::from(atomic::Atomic::from(1f64)),
709 Item::from(atomic::Atomic::from(2f64)),
710 ]))
711 );
712 }
713
714 #[test]
715 fn test_many_cast_untyped() {
716 let namespaces = Namespaces::default();
717 let sequence_type = parse_sequence_type("xs:integer*", &namespaces).unwrap();
718
719 let mut xot = Xot::new();
720 let doc = xot.parse(r#"<doc><a>1</a><b>2</b></doc>"#).unwrap();
721 let doc = xot.document_element(doc).unwrap();
722 let a = xot.first_child(doc).unwrap();
723 let b = xot.next_sibling(a).unwrap();
724
725 let right_sequence = Sequence::from(vec![Item::from(a), Item::from(b)]);
726
727 let static_context = context::StaticContext::default();
728
729 let right_result = right_sequence.sequence_type_matching_function_conversion(
730 &sequence_type,
731 &static_context,
732 &xot,
733 &|_| unreachable!(),
734 );
735 assert_eq!(
737 right_result,
738 Ok(Sequence::from(vec![
739 Item::from(atomic::Atomic::from(ibig!(1))),
740 Item::from(atomic::Atomic::from(ibig!(2))),
741 ]))
742 );
743 }
744
745 #[test]
746 fn test_any_function_test() {
747 let namespaces = Namespaces::default();
748 let sequence_type = parse_sequence_type("function(*)", &namespaces).unwrap();
749 let function =
750 function::StaticFunctionData::new(function::StaticFunctionId(1), vec![]).into();
751 let right_sequence = Sequence::from(vec![Item::Function(function)]);
752
753 let signature = function::Signature::new(
754 vec![Some(
755 parse_sequence_type("xs:integer", &namespaces).unwrap(),
756 )],
757 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
758 );
759
760 let xot = Xot::new();
761
762 let right_result =
763 right_sequence
764 .clone()
765 .sequence_type_matching(&sequence_type, &xot, &|_| &signature);
766 assert_eq!(&right_result.unwrap(), &right_sequence);
767 }
768
769 #[test]
770 fn test_function_test_same_parameters() {
771 let namespaces = Namespaces::default();
772 let sequence_type =
773 parse_sequence_type("function(xs:integer) as xs:integer", &namespaces).unwrap();
774 let function =
775 function::StaticFunctionData::new(function::StaticFunctionId(1), vec![]).into();
776 let right_sequence = Sequence::from(vec![Item::Function(function)]);
777
778 let signature = function::Signature::new(
779 vec![Some(
780 parse_sequence_type("xs:integer", &namespaces).unwrap(),
781 )],
782 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
783 );
784
785 let xot = Xot::new();
786
787 let right_result =
788 right_sequence
789 .clone()
790 .sequence_type_matching(&sequence_type, &xot, &|_| &signature);
791 assert_eq!(&right_result.unwrap(), &right_sequence);
792 }
793
794 #[test]
795 fn test_function_test_derived_parameters() {
796 let namespaces = Namespaces::default();
797 let sequence_type =
798 parse_sequence_type("function(xs:integer) as xs:integer", &namespaces).unwrap();
799 let function =
800 function::StaticFunctionData::new(function::StaticFunctionId(1), vec![]).into();
801 let right_sequence = Sequence::from(vec![Item::Function(function)]);
802
803 let signature = function::Signature::new(
804 vec![Some(
805 parse_sequence_type("xs:integer", &namespaces).unwrap(),
806 )],
807 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
808 );
809
810 let xot = Xot::new();
811
812 let right_result =
813 right_sequence
814 .clone()
815 .sequence_type_matching(&sequence_type, &xot, &|_| &signature);
816 assert_eq!(&right_result.unwrap(), &right_sequence);
817 }
818
819 #[test]
820 fn test_function_test_wrong_arity() {
821 let namespaces = Namespaces::default();
822 let sequence_type =
823 parse_sequence_type("function(xs:integer) as xs:integer", &namespaces).unwrap();
824 let function =
825 function::StaticFunctionData::new(function::StaticFunctionId(1), vec![]).into();
826 let wrong_sequence = Sequence::from(vec![Item::Function(function)]);
827
828 let signature = function::Signature::new(
829 vec![
830 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
831 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
832 ],
833 Some(parse_sequence_type("xs:integer", &namespaces).unwrap()),
834 );
835
836 let xot = Xot::new();
837
838 let wrong_result =
839 wrong_sequence
840 .clone()
841 .sequence_type_matching(&sequence_type, &xot, &|_| &signature);
842 assert_eq!(wrong_result, Err(error::Error::XPTY0004));
843 }
844}