1pub(crate) mod booleans;
41pub mod callable;
42pub(crate) mod construct;
43pub mod context;
44pub(crate) mod controlflow;
45pub(crate) mod datetime;
46pub(crate) mod functions;
47pub(crate) mod grouping;
48mod keys;
49pub(crate) mod logic;
50pub(crate) mod misc;
51pub(crate) mod navigate;
52pub mod numbers;
53pub(crate) mod strings;
54pub mod template;
55pub(crate) mod variables;
56
57#[allow(unused_imports)]
58use crate::item::Sequence;
59use crate::item::{Item, Node, NodeType, SequenceTrait};
60use crate::namespace::NamespaceMap;
61use crate::output::OutputSpec;
62use crate::pattern::Pattern;
63use crate::qname::QualifiedName;
64use crate::transform::callable::ActualParameters;
65use crate::transform::context::{Context, ContextBuilder, StaticContext};
66use crate::transform::numbers::Numbering;
67use crate::value::Operator;
68#[allow(unused_imports)]
69use crate::value::Value;
70use crate::xdmerror::{Error, ErrorKind};
71use std::convert::TryFrom;
72use std::fmt;
73use std::fmt::{Debug, Formatter};
74use std::rc::Rc;
75use url::Url;
76
77#[derive(Clone)]
79pub enum Transform<N: Node> {
80 Root,
82 ContextItem,
84 CurrentItem,
86
87 Compose(Vec<Transform<N>>),
90 Step(NodeMatch),
92 Filter(Box<Transform<N>>),
98
99 Empty,
101 Literal(Item<N>),
103 LiteralElement(Rc<QualifiedName>, Box<Transform<N>>),
105 Element(Box<Transform<N>>, Box<Transform<N>>),
107 LiteralText(Box<Transform<N>>, OutputSpec),
109 LiteralAttribute(Rc<QualifiedName>, Box<Transform<N>>),
112 LiteralComment(Box<Transform<N>>),
114 LiteralProcessingInstruction(Box<Transform<N>>, Box<Transform<N>>),
116 SequenceItems(Vec<Transform<N>>),
118
119 Copy(Box<Transform<N>>, Box<Transform<N>>),
122 DeepCopy(Box<Transform<N>>),
124
125 Or(Vec<Transform<N>>),
127 And(Vec<Transform<N>>),
129
130 GeneralComparison(Operator, Box<Transform<N>>, Box<Transform<N>>),
133 ValueComparison(Operator, Box<Transform<N>>, Box<Transform<N>>),
136
137 Concat(Vec<Transform<N>>),
139 Range(Box<Transform<N>>, Box<Transform<N>>),
142 Arithmetic(Vec<ArithmeticOperand<N>>),
144
145 Loop(Vec<(String, Transform<N>)>, Box<Transform<N>>),
147 Switch(Vec<(Transform<N>, Transform<N>)>, Box<Transform<N>>),
149
150 ForEach(
152 Option<Grouping<N>>,
153 Box<Transform<N>>,
154 Box<Transform<N>>,
155 Vec<(Order, Transform<N>)>,
156 ),
157 ApplyTemplates(
160 Box<Transform<N>>,
161 Option<Rc<QualifiedName>>,
162 Vec<(Order, Transform<N>)>,
163 ),
164 ApplyImports,
166 NextMatch,
167
168 Union(Vec<Transform<N>>),
170
171 Call(Box<Transform<N>>, Vec<Transform<N>>, Rc<NamespaceMap>),
174
175 VariableDeclaration(
178 String,
179 Box<Transform<N>>,
180 Box<Transform<N>>,
181 Rc<NamespaceMap>,
182 ),
183 VariableReference(String, Rc<NamespaceMap>),
186
187 SetAttribute(Rc<QualifiedName>, Box<Transform<N>>),
190
191 Position,
193 Last,
194 Count(Box<Transform<N>>),
195 LocalName(Option<Box<Transform<N>>>),
196 Name(Option<Box<Transform<N>>>),
197 String(Box<Transform<N>>),
198 StartsWith(Box<Transform<N>>, Box<Transform<N>>),
199 EndsWith(Box<Transform<N>>, Box<Transform<N>>),
200 Contains(Box<Transform<N>>, Box<Transform<N>>),
201 Substring(
202 Box<Transform<N>>,
203 Box<Transform<N>>,
204 Option<Box<Transform<N>>>,
205 ),
206 SubstringBefore(Box<Transform<N>>, Box<Transform<N>>),
207 SubstringAfter(Box<Transform<N>>, Box<Transform<N>>),
208 NormalizeSpace(Option<Box<Transform<N>>>),
209 Translate(Box<Transform<N>>, Box<Transform<N>>, Box<Transform<N>>),
210 GenerateId(Option<Box<Transform<N>>>),
211 Boolean(Box<Transform<N>>),
212 Not(Box<Transform<N>>),
213 True,
214 False,
215 Number(Box<Transform<N>>),
216 Sum(Box<Transform<N>>),
217 Avg(Box<Transform<N>>),
218 Min(Box<Transform<N>>),
219 Max(Box<Transform<N>>),
220 Floor(Box<Transform<N>>),
221 Ceiling(Box<Transform<N>>),
222 Round(Box<Transform<N>>, Option<Box<Transform<N>>>),
223 CurrentDateTime,
224 CurrentDate,
225 CurrentTime,
226 FormatDateTime(
227 Box<Transform<N>>,
228 Box<Transform<N>>,
229 Option<Box<Transform<N>>>,
230 Option<Box<Transform<N>>>,
231 Option<Box<Transform<N>>>,
232 ),
233 FormatDate(
234 Box<Transform<N>>,
235 Box<Transform<N>>,
236 Option<Box<Transform<N>>>,
237 Option<Box<Transform<N>>>,
238 Option<Box<Transform<N>>>,
239 ),
240 FormatTime(
241 Box<Transform<N>>,
242 Box<Transform<N>>,
243 Option<Box<Transform<N>>>,
244 Option<Box<Transform<N>>>,
245 Option<Box<Transform<N>>>,
246 ),
247 FormatNumber(
248 Box<Transform<N>>,
249 Box<Transform<N>>,
250 Option<Box<Transform<N>>>,
251 ),
252 FormatInteger(Box<Transform<N>>, Box<Transform<N>>),
258 GenerateIntegers(Box<Transform<N>>, Box<Transform<N>>, Box<Numbering<N>>),
265 CurrentGroup,
266 CurrentGroupingKey,
267 Key(
271 Box<Transform<N>>,
272 Box<Transform<N>>,
273 Option<Box<Transform<N>>>,
274 Rc<NamespaceMap>,
275 ),
276 SystemProperty(Box<Transform<N>>, Rc<NamespaceMap>),
278 AvailableSystemProperties,
279 Document(Box<Transform<N>>, Option<Box<Transform<N>>>),
281
282 Invoke(Rc<QualifiedName>, ActualParameters<N>, Rc<NamespaceMap>),
284
285 Message(
287 Box<Transform<N>>,
288 Option<Box<Transform<N>>>,
289 Box<Transform<N>>,
290 Box<Transform<N>>,
291 ),
292
293 NotImplemented(String),
296
297 Error(ErrorKind, String),
299}
300
301impl<N: Node> Debug for Transform<N> {
302 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
303 match self {
304 Transform::Root => write!(f, "root node"),
305 Transform::ContextItem => write!(f, "context item"),
306 Transform::CurrentItem => write!(f, "current item"),
307 Transform::SequenceItems(v) => write!(f, "Sequence of {} items", v.len()),
308 Transform::Compose(v) => {
309 write!(f, "Compose {} steps [", v.len()).expect("unable to format step");
310 v.iter().for_each(|s| {
311 s.fmt(f).expect("unable to format step");
312 write!(f, "; ").expect("unable to format step")
313 });
314 write!(f, "]")
315 }
316 Transform::Step(nm) => write!(f, "Step matching {}", nm),
317 Transform::Filter(_) => write!(f, "Filter"),
318 Transform::Empty => write!(f, "Empty"),
319 Transform::Literal(_) => write!(f, "literal value"),
320 Transform::LiteralElement(qn, _) => write!(f, "literal element named \"{}\"", qn),
321 Transform::Element(_, _) => write!(f, "constructed element"),
322 Transform::LiteralText(_, b) => write!(f, "literal text (disable escaping {:?})", b),
323 Transform::LiteralAttribute(qn, _) => write!(f, "literal attribute named \"{}\"", qn),
324 Transform::LiteralComment(_) => write!(f, "literal comment"),
325 Transform::LiteralProcessingInstruction(_, _) => {
326 write!(f, "literal processing-instruction")
327 }
328 Transform::Copy(_, _) => write!(f, "shallow copy"),
329 Transform::DeepCopy(_) => write!(f, "deep copy"),
330 Transform::GeneralComparison(o, v, u) => {
331 write!(f, "general comparison {} of {:?} and {:?}", o, v, u)
332 }
333 Transform::ValueComparison(o, v, u) => {
334 write!(f, "value comparison {} of {:?} and {:?}", o, v, u)
335 }
336 Transform::Concat(o) => write!(f, "Concatenate {} operands", o.len()),
337 Transform::Range(_, _) => write!(f, "range"),
338 Transform::Arithmetic(o) => write!(f, "Arithmetic {} operands", o.len()),
339 Transform::And(o) => write!(f, "AND {} operands", o.len()),
340 Transform::Or(o) => write!(f, "OR {} operands", o.len()),
341 Transform::Loop(_, _) => write!(f, "loop"),
342 Transform::Switch(c, _) => write!(f, "switch {} clauses", c.len()),
343 Transform::ForEach(_g, _, _, o) => write!(f, "for-each ({} sort keys)", o.len()),
344 Transform::Union(v) => {
345 write!(f, "union of {} operands", v.len()).ok();
346 v.iter().for_each(|o| {
347 write!(f, "\noperand: {:?}", o).ok();
348 });
349 Ok(())
350 }
351 Transform::ApplyTemplates(_, m, o) => {
352 write!(f, "Apply templates (mode {:?}, {} sort keys)", m, o.len())
353 }
354 Transform::Call(_, a, _) => write!(f, "Call transform with {} arguments", a.len()),
355 Transform::ApplyImports => write!(f, "Apply imports"),
356 Transform::NextMatch => write!(f, "next-match"),
357 Transform::VariableDeclaration(n, _, _, _) => write!(f, "declare variable \"{}\"", n),
358 Transform::VariableReference(n, _) => write!(f, "reference variable \"{}\"", n),
359 Transform::SetAttribute(n, _) => write!(f, "set attribute named \"{}\"", n),
360 Transform::Position => write!(f, "position"),
361 Transform::Last => write!(f, "last"),
362 Transform::Count(_s) => write!(f, "count()"),
363 Transform::Name(_n) => write!(f, "name()"),
364 Transform::LocalName(_n) => write!(f, "local-name()"),
365 Transform::String(s) => write!(f, "string({:?})", s),
366 Transform::StartsWith(s, t) => write!(f, "starts-with({:?}, {:?})", s, t),
367 Transform::EndsWith(s, t) => write!(f, "ends-with({:?}, {:?})", s, t),
368 Transform::Contains(s, t) => write!(f, "contains({:?}, {:?})", s, t),
369 Transform::Substring(s, t, _l) => write!(f, "substring({:?}, {:?}, ...)", s, t),
370 Transform::SubstringBefore(s, t) => write!(f, "substring-before({:?}, {:?})", s, t),
371 Transform::SubstringAfter(s, t) => write!(f, "substring-after({:?}, {:?})", s, t),
372 Transform::NormalizeSpace(_s) => write!(f, "normalize-space()"),
373 Transform::Translate(s, t, u) => write!(f, "translate({:?}, {:?}, {:?})", s, t, u),
374 Transform::GenerateId(_) => write!(f, "generate-id()"),
375 Transform::Boolean(b) => write!(f, "boolean({:?})", b),
376 Transform::Not(b) => write!(f, "not({:?})", b),
377 Transform::True => write!(f, "true"),
378 Transform::False => write!(f, "false"),
379 Transform::Number(n) => write!(f, "number({:?})", n),
380 Transform::Sum(n) => write!(f, "sum({:?})", n),
381 Transform::Avg(n) => write!(f, "avg({:?})", n),
382 Transform::Min(n) => write!(f, "min({:?})", n),
383 Transform::Max(n) => write!(f, "max({:?})", n),
384 Transform::Floor(n) => write!(f, "floor({:?})", n),
385 Transform::Ceiling(n) => write!(f, "ceiling({:?})", n),
386 Transform::Round(n, _p) => write!(f, "round({:?},...)", n),
387 Transform::CurrentDateTime => write!(f, "current-date-time"),
388 Transform::CurrentDate => write!(f, "current-date"),
389 Transform::CurrentTime => write!(f, "current-time"),
390 Transform::FormatDateTime(p, q, _, _, _) => {
391 write!(f, "format-date-time({:?}, {:?}, ...)", p, q)
392 }
393 Transform::FormatDate(p, q, _, _, _) => write!(f, "format-date({:?}, {:?}, ...)", p, q),
394 Transform::FormatTime(p, q, _, _, _) => write!(f, "format-time({:?}, {:?}, ...)", p, q),
395 Transform::FormatNumber(v, p, _) => write!(f, "format-number({:?}, {:?})", v, p),
396 Transform::FormatInteger(i, s) => write!(f, "format-integer({:?}, {:?})", i, s),
397 Transform::GenerateIntegers(_start_at, _select, _n) => write!(f, "generate-integers"),
398 Transform::CurrentGroup => write!(f, "current-group"),
399 Transform::CurrentGroupingKey => write!(f, "current-grouping-key"),
400 Transform::Key(s, _, _, _) => write!(f, "key({:?}, ...)", s),
401 Transform::SystemProperty(p, _) => write!(f, "system-properties({:?})", p),
402 Transform::AvailableSystemProperties => write!(f, "available-system-properties"),
403 Transform::Document(uris, _) => write!(f, "document({:?})", uris),
404 Transform::Invoke(qn, _a, _) => write!(f, "invoke \"{}\"", qn),
405 Transform::Message(_, _, _, _) => write!(f, "message"),
406 Transform::NotImplemented(s) => write!(f, "Not implemented: \"{}\"", s),
407 Transform::Error(k, s) => write!(f, "Error: {} \"{}\"", k, s),
408 }
409 }
410}
411
412pub fn in_scope_namespaces<N: Node>(n: Option<N>) -> Rc<NamespaceMap> {
414 if let Some(nn) = n {
415 Rc::new(nn.namespace_iter().fold(NamespaceMap::new(), |mut hm, ns| {
416 hm.insert(Some(ns.name().localname()), ns.value());
417 hm
418 }))
419 } else {
420 Rc::new(NamespaceMap::new())
421 }
422}
423
424#[derive(Clone, PartialEq, Debug)]
426pub enum Order {
427 Ascending,
428 Descending,
429}
430
431pub(crate) fn do_sort<
433 N: Node,
434 F: FnMut(&str) -> Result<(), Error>,
435 G: FnMut(&str) -> Result<N, Error>,
436 H: FnMut(&Url) -> Result<String, Error>,
437>(
438 seq: &mut Sequence<N>,
439 o: &Vec<(Order, Transform<N>)>,
440 ctxt: &Context<N>,
441 stctxt: &mut StaticContext<N, F, G, H>,
442) -> Result<(), Error> {
443 if !o.is_empty() {
446 seq.sort_by_cached_key(|k| {
447 let key_seq = ContextBuilder::from(ctxt)
449 .context(vec![k.clone()])
450 .build()
451 .dispatch(stctxt, &o[0].1)
452 .expect("unable to determine key value");
453 key_seq.to_string()
457 });
458 if o[0].0 == Order::Descending {
459 seq.reverse();
460 }
461 }
462 Ok(())
463}
464
465#[derive(Clone, Debug)]
469pub enum Grouping<N: Node> {
470 By(Vec<Transform<N>>),
471 StartingWith(Box<Pattern<N>>),
472 EndingWith(Box<Pattern<N>>),
473 Adjacent(Vec<Transform<N>>),
474}
475
476impl<N: Node> Grouping<N> {
477 fn to_string(&self) -> String {
478 match self {
479 Grouping::By(_) => "group-by".to_string(),
480 Grouping::Adjacent(_) => "group-adjacent".to_string(),
481 Grouping::StartingWith(_) => "group-starting-with".to_string(),
482 Grouping::EndingWith(_) => "group-ending-with".to_string(),
483 }
484 }
485}
486
487impl<N: Node> fmt::Display for Grouping<N> {
488 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
489 write!(f, "{}", self.to_string())
490 }
491}
492
493#[derive(Clone, Debug)]
494pub struct NodeMatch {
495 pub axis: Axis,
496 pub nodetest: NodeTest,
497}
498
499impl NodeMatch {
500 pub fn new(axis: Axis, nodetest: NodeTest) -> Self {
501 NodeMatch { axis, nodetest }
502 }
503 pub fn matches_item<N: Node>(&self, i: &Item<N>) -> bool {
504 match i {
505 Item::Node(n) => self.matches(n),
506 _ => false,
507 }
508 }
509 pub fn matches<N: Node>(&self, n: &N) -> bool {
510 match &self.nodetest {
511 NodeTest::Name(t) => {
512 match n.node_type() {
513 NodeType::Element | NodeType::Attribute => {
514 match &t.name {
516 Some(a) => match a {
517 WildcardOrName::Wildcard => true,
518 WildcardOrName::Name(s) => *s == n.name().localname(),
519 },
520 None => false,
521 }
522 }
523 _ => false,
524 }
525 }
526 NodeTest::Kind(k) => {
527 match k {
528 KindTest::Document => matches!(n.node_type(), NodeType::Document),
529 KindTest::Element => matches!(n.node_type(), NodeType::Element),
530 KindTest::PI => matches!(n.node_type(), NodeType::ProcessingInstruction),
531 KindTest::Comment => matches!(n.node_type(), NodeType::Comment),
532 KindTest::Text => matches!(n.node_type(), NodeType::Text),
533 KindTest::Any => !matches!(n.node_type(), NodeType::Document),
535 KindTest::Attribute
536 | KindTest::SchemaElement
537 | KindTest::SchemaAttribute
538 | KindTest::Namespace => false, }
540 }
541 }
542 }
543}
544
545impl fmt::Display for NodeMatch {
546 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
547 write!(f, "node match {} {}", self.axis, self.nodetest)
548 }
549}
550
551#[derive(Clone, Debug)]
552pub enum NodeTest {
553 Kind(KindTest),
554 Name(NameTest),
555}
556
557impl NodeTest {
558 pub fn matches<N: Node>(&self, i: &Item<N>) -> bool {
559 match i {
560 Item::Node(_) => match self {
561 NodeTest::Kind(k) => k.matches(i),
562 NodeTest::Name(nm) => nm.matches(i),
563 },
564 _ => false,
565 }
566 }
567}
568
569impl fmt::Display for NodeTest {
570 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
571 match self {
572 NodeTest::Kind(k) => write!(f, "kind test {}", k),
573 NodeTest::Name(nm) => write!(f, "name test {}", nm),
574 }
575 }
576}
577
578impl TryFrom<&str> for NodeTest {
579 type Error = Error;
580
581 fn try_from(s: &str) -> Result<Self, Self::Error> {
582 let tok: Vec<&str> = s.split(':').collect();
584 match tok.len() {
585 1 => {
586 if tok[0] == "*" {
588 Ok(NodeTest::Name(NameTest {
589 name: Some(WildcardOrName::Wildcard),
590 ns: None,
591 prefix: None,
592 }))
593 } else {
594 Ok(NodeTest::Name(NameTest {
595 name: Some(WildcardOrName::Name(Rc::new(Value::from(tok[0])))),
596 ns: None,
597 prefix: None,
598 }))
599 }
600 }
601 2 => {
602 if tok[0] == "*" {
604 if tok[1] == "*" {
605 Ok(NodeTest::Name(NameTest {
606 name: Some(WildcardOrName::Wildcard),
607 ns: Some(WildcardOrName::Wildcard),
608 prefix: None,
609 }))
610 } else {
611 Ok(NodeTest::Name(NameTest {
612 name: Some(WildcardOrName::Name(Rc::new(Value::from(tok[1])))),
613 ns: Some(WildcardOrName::Wildcard),
614 prefix: None,
615 }))
616 }
617 } else if tok[1] == "*" {
618 Ok(NodeTest::Name(NameTest {
619 name: Some(WildcardOrName::Wildcard),
620 ns: None,
621 prefix: Some(Rc::new(Value::from(tok[0]))),
622 }))
623 } else {
624 Ok(NodeTest::Name(NameTest {
625 name: Some(WildcardOrName::Name(Rc::new(Value::from(tok[1])))),
626 ns: None,
627 prefix: Some(Rc::new(Value::from(tok[0]))),
628 }))
629 }
630 }
631 _ => Result::Err(Error::new(
632 ErrorKind::TypeError,
633 "invalid NodeTest".to_string(),
634 )),
635 }
636 }
637}
638
639#[derive(Copy, Clone, Debug)]
640pub enum KindTest {
641 Document,
642 Element,
643 Attribute,
644 SchemaElement,
645 SchemaAttribute,
646 PI,
647 Comment,
648 Text,
649 Namespace,
650 Any,
651}
652
653impl fmt::Display for KindTest {
654 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
655 match self {
656 KindTest::Document => write!(f, "document"),
657 KindTest::Element => write!(f, "element"),
658 KindTest::Attribute => write!(f, "attribute"),
659 KindTest::SchemaElement => write!(f, "schema element"),
660 KindTest::SchemaAttribute => write!(f, "schema attribute"),
661 KindTest::PI => write!(f, "processing instruction"),
662 KindTest::Comment => write!(f, "comment"),
663 KindTest::Text => write!(f, "text"),
664 KindTest::Namespace => write!(f, "namespace"),
665 KindTest::Any => write!(f, "any node"),
666 }
667 }
668}
669
670impl KindTest {
671 pub fn matches<N: Node>(&self, i: &Item<N>) -> bool {
673 match i {
674 Item::Node(n) => {
675 match (self, n.node_type()) {
676 (KindTest::Document, NodeType::Document) => true,
677 (KindTest::Document, _) => false,
678 (KindTest::Element, NodeType::Element) => true,
679 (KindTest::Element, _) => false,
680 (KindTest::Attribute, NodeType::Attribute) => true,
681 (KindTest::Attribute, _) => false,
682 (KindTest::SchemaElement, _) => false, (KindTest::SchemaAttribute, _) => false, (KindTest::PI, NodeType::ProcessingInstruction) => true,
685 (KindTest::PI, _) => false,
686 (KindTest::Comment, NodeType::Comment) => true,
687 (KindTest::Comment, _) => false,
688 (KindTest::Text, NodeType::Text) => true,
689 (KindTest::Text, _) => false,
690 (KindTest::Namespace, _) => false, (KindTest::Any, _) => true,
692 }
693 }
694 _ => false,
695 }
696 }
697 pub fn to_string(&self) -> &'static str {
698 match self {
699 KindTest::Document => "DocumentTest",
700 KindTest::Element => "ElementTest",
701 KindTest::Attribute => "AttributeTest",
702 KindTest::SchemaElement => "SchemaElementTest",
703 KindTest::SchemaAttribute => "SchemaAttributeTest",
704 KindTest::PI => "PITest",
705 KindTest::Comment => "CommentTest",
706 KindTest::Text => "TextTest",
707 KindTest::Namespace => "NamespaceNodeTest",
708 KindTest::Any => "AnyKindTest",
709 }
710 }
711}
712
713#[derive(Clone, Debug)]
714pub struct NameTest {
715 pub ns: Option<WildcardOrName>,
716 pub prefix: Option<Rc<Value>>,
717 pub name: Option<WildcardOrName>,
718}
719
720impl NameTest {
721 pub fn new(
722 ns: Option<WildcardOrName>,
723 prefix: Option<Rc<Value>>,
724 name: Option<WildcardOrName>,
725 ) -> Self {
726 NameTest { ns, prefix, name }
727 }
728 pub fn matches<N: Node>(&self, i: &Item<N>) -> bool {
731 match i {
732 Item::Node(n) => {
733 match n.node_type() {
734 NodeType::Element | NodeType::ProcessingInstruction | NodeType::Attribute => {
735 match (
738 self.ns.as_ref(),
739 self.name.as_ref(),
740 n.name().namespace_uri(),
741 n.name().localname_to_string().as_str(),
742 ) {
743 (None, None, _, _) => false,
744 (None, Some(WildcardOrName::Wildcard), None, _) => true,
745 (None, Some(WildcardOrName::Wildcard), Some(_), _) => false,
746 (None, Some(WildcardOrName::Name(_)), None, "") => false,
747 (None, Some(WildcardOrName::Name(wn)), None, qn) => {
748 wn.to_string() == qn
749 }
750 (None, Some(WildcardOrName::Name(_)), Some(_), _) => false,
751 (Some(_), None, _, _) => false, (
753 Some(WildcardOrName::Wildcard),
754 Some(WildcardOrName::Wildcard),
755 _,
756 _,
757 ) => true,
758 (
759 Some(WildcardOrName::Wildcard),
760 Some(WildcardOrName::Name(_)),
761 _,
762 "",
763 ) => false,
764 (
765 Some(WildcardOrName::Wildcard),
766 Some(WildcardOrName::Name(wn)),
767 _,
768 qn,
769 ) => wn.to_string() == qn,
770 (Some(WildcardOrName::Name(_)), Some(_), None, _) => false,
771 (
772 Some(WildcardOrName::Name(wnsuri)),
773 Some(WildcardOrName::Name(wn)),
774 Some(qnsuri),
775 qn,
776 ) => wnsuri.clone() == qnsuri && wn.to_string() == qn,
777 _ => false, }
779 }
780 _ => false, }
782 }
783 _ => false, }
785 }
786}
787
788impl fmt::Display for NameTest {
789 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
790 let result = if self.name.is_some() {
791 match self.name.as_ref().unwrap() {
792 WildcardOrName::Wildcard => "*".to_string(),
793 WildcardOrName::Name(n) => n.to_string(),
794 }
795 } else {
796 "--no name--".to_string()
797 };
798 f.write_str(result.as_str())
799 }
800}
801
802#[derive(Clone, Debug)]
803pub enum WildcardOrName {
804 Wildcard,
805 Name(Rc<Value>),
806}
807
808#[derive(Copy, Clone, Debug, PartialEq)]
809pub enum Axis {
810 Child,
811 Descendant,
812 DescendantOrSelf,
813 DescendantOrSelfOrRoot,
814 Attribute,
815 SelfAttribute, SelfAxis,
817 SelfDocument, SelfNamespace, Following,
820 FollowingSibling,
821 Namespace,
822 Parent,
823 ParentDocument, Ancestor,
825 AncestorOrSelf,
826 AncestorOrSelfOrRoot, Preceding,
828 PrecedingSibling,
829 Unknown,
830}
831
832impl From<&str> for Axis {
833 fn from(s: &str) -> Self {
834 match s {
835 "child" => Axis::Child,
836 "descendant" => Axis::Descendant,
837 "descendant-or-self" => Axis::DescendantOrSelf,
838 "attribute" => Axis::Attribute,
839 "self" => Axis::SelfAxis,
840 "following" => Axis::Following,
841 "following-sibling" => Axis::FollowingSibling,
842 "namespace" => Axis::Namespace,
843 "parent" => Axis::Parent,
844 "ancestor" => Axis::Ancestor,
845 "ancestor-or-self" => Axis::AncestorOrSelf,
846 "preceding" => Axis::Preceding,
847 "preceding-sibling" => Axis::PrecedingSibling,
848 _ => Axis::Unknown,
849 }
850 }
851}
852
853impl fmt::Display for Axis {
854 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
855 let result = match self {
856 Axis::Child => "child".to_string(),
857 Axis::Descendant => "descendant".to_string(),
858 Axis::DescendantOrSelf => "descendant-or-self".to_string(),
859 Axis::DescendantOrSelfOrRoot => "descendant-or-self-or-root".to_string(),
860 Axis::Attribute => "attribute".to_string(),
861 Axis::SelfAttribute => "self-attribute".to_string(),
862 Axis::SelfAxis => "self".to_string(),
863 Axis::SelfDocument => "self-document".to_string(),
864 Axis::Following => "following".to_string(),
865 Axis::FollowingSibling => "following-sibling".to_string(),
866 Axis::Namespace => "namespace".to_string(),
867 Axis::Parent => "parent".to_string(),
868 Axis::ParentDocument => "parent-document".to_string(),
869 Axis::Ancestor => "ancestor".to_string(),
870 Axis::AncestorOrSelf => "ancestor-or-self".to_string(),
871 Axis::Preceding => "preceding".to_string(),
872 Axis::PrecedingSibling => "preceding-sibling".to_string(),
873 _ => "unknown".to_string(),
874 };
875 f.write_str(result.as_str())
876 }
877}
878
879#[derive(Clone, Debug)]
880pub struct ArithmeticOperand<N: Node> {
881 pub op: ArithmeticOperator,
882 pub operand: Transform<N>,
883}
884
885impl<N: Node> ArithmeticOperand<N> {
886 pub fn new(op: ArithmeticOperator, operand: Transform<N>) -> Self {
887 ArithmeticOperand { op, operand }
888 }
889}
890
891#[derive(Copy, Clone, Debug, PartialEq)]
892pub enum ArithmeticOperator {
893 Noop,
894 Add,
895 Multiply,
896 Divide,
897 IntegerDivide,
898 Subtract,
899 Modulo,
900}
901
902impl fmt::Display for ArithmeticOperator {
903 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
904 match self {
905 ArithmeticOperator::Add => f.write_str("+"),
906 ArithmeticOperator::Multiply => f.write_str("*"),
907 ArithmeticOperator::Divide => f.write_str("div"),
908 ArithmeticOperator::IntegerDivide => f.write_str("idiv"),
909 ArithmeticOperator::Subtract => f.write_str("-"),
910 ArithmeticOperator::Modulo => f.write_str("mod"),
911 ArithmeticOperator::Noop => f.write_str("noop"),
912 }
913 }
914}
915
916impl From<&str> for ArithmeticOperator {
917 fn from(a: &str) -> Self {
918 match a {
919 "+" => ArithmeticOperator::Add,
920 "*" => ArithmeticOperator::Multiply,
921 "div" => ArithmeticOperator::Divide,
922 "idiv" => ArithmeticOperator::IntegerDivide,
923 "-" => ArithmeticOperator::Subtract,
924 "mod" => ArithmeticOperator::Modulo,
925 _ => ArithmeticOperator::Noop,
926 }
927 }
928}
929
930impl From<String> for ArithmeticOperator {
931 fn from(a: String) -> Self {
932 match a.as_str() {
933 "+" => ArithmeticOperator::Add,
934 "*" => ArithmeticOperator::Multiply,
935 "div" => ArithmeticOperator::Divide,
936 "idiv" => ArithmeticOperator::IntegerDivide,
937 "-" => ArithmeticOperator::Subtract,
938 "mod" => ArithmeticOperator::Modulo,
939 _ => ArithmeticOperator::Noop,
940 }
941 }
942}