1use std::rc::Rc;
4use url::Url;
5
6use crate::item::{Item, Node, Sequence, SequenceTrait};
7use crate::transform::context::{Context, StaticContext};
8use crate::transform::Transform;
9use crate::value::{Operator, Value};
10use crate::xdmerror::{Error, ErrorKind};
11
12pub(crate) fn tr_or<
14 N: Node,
15 F: FnMut(&str) -> Result<(), Error>,
16 G: FnMut(&str) -> Result<N, Error>,
17 H: FnMut(&Url) -> Result<String, Error>,
18>(
19 ctxt: &Context<N>,
20 stctxt: &mut StaticContext<N, F, G, H>,
21 v: &Vec<Transform<N>>,
22) -> Result<Sequence<N>, Error> {
23 let mut b = false;
25 let mut i = 0;
26 loop {
27 match v.get(i) {
28 Some(a) => {
29 if ctxt.dispatch(stctxt, a)?.to_bool() {
30 b = true;
31 break;
32 }
33 i += 1;
34 }
35 None => break,
36 }
37 }
38 Ok(vec![Item::Value(Rc::new(Value::from(b)))])
39}
40
41pub(crate) fn tr_and<
43 N: Node,
44 F: FnMut(&str) -> Result<(), Error>,
45 G: FnMut(&str) -> Result<N, Error>,
46 H: FnMut(&Url) -> Result<String, Error>,
47>(
48 ctxt: &Context<N>,
49 stctxt: &mut StaticContext<N, F, G, H>,
50 v: &Vec<Transform<N>>,
51) -> Result<Sequence<N>, Error> {
52 let mut b = true;
54 let mut i = 0;
55 loop {
56 match v.get(i) {
57 Some(a) => {
58 if !ctxt.dispatch(stctxt, a)?.to_bool() {
59 b = false;
60 break;
61 }
62 i += 1;
63 }
64 None => break,
65 }
66 }
67 Ok(vec![Item::Value(Rc::new(Value::from(b)))])
68}
69
70pub(crate) fn general_comparison<
72 N: Node,
73 F: FnMut(&str) -> Result<(), Error>,
74 G: FnMut(&str) -> Result<N, Error>,
75 H: FnMut(&Url) -> Result<String, Error>,
76>(
77 ctxt: &Context<N>,
78 stctxt: &mut StaticContext<N, F, G, H>,
79 o: &Operator,
80 l: &Transform<N>,
81 r: &Transform<N>,
82) -> Result<Sequence<N>, Error> {
83 let left = ctxt.dispatch(stctxt, l)?;
84 let right = ctxt.dispatch(stctxt, r)?;
85
86 let mut b = false;
87 for i in left {
88 for j in &right {
89 b = i.compare(j, *o).unwrap();
90 if b {
91 break;
92 }
93 }
94 if b {
95 break;
96 }
97 }
98
99 Ok(vec![Item::Value(Rc::new(Value::from(b)))])
100}
101
102pub(crate) fn value_comparison<
104 N: Node,
105 F: FnMut(&str) -> Result<(), Error>,
106 G: FnMut(&str) -> Result<N, Error>,
107 H: FnMut(&Url) -> Result<String, Error>,
108>(
109 ctxt: &Context<N>,
110 stctxt: &mut StaticContext<N, F, G, H>,
111 o: &Operator,
112 l: &Transform<N>,
113 r: &Transform<N>,
114) -> Result<Sequence<N>, Error> {
115 let left = ctxt.dispatch(stctxt, l)?;
116 if left.len() != 1 {
117 return Err(Error::new(
118 ErrorKind::TypeError,
119 String::from("left-hand sequence is not a singleton sequence"),
120 ));
121 }
122 let right = ctxt.dispatch(stctxt, r)?;
123 if right.len() != 1 {
124 return Err(Error::new(
125 ErrorKind::TypeError,
126 String::from("right-hand sequence is not a singleton sequence"),
127 ));
128 }
129
130 Ok(vec![Item::Value(Rc::new(Value::from(
131 left[0].compare(&right[0], *o)?,
132 )))])
133}
134
135pub(crate) fn union<
139 N: Node,
140 F: FnMut(&str) -> Result<(), Error>,
141 G: FnMut(&str) -> Result<N, Error>,
142 H: FnMut(&Url) -> Result<String, Error>,
143>(
144 ctxt: &Context<N>,
145 stctxt: &mut StaticContext<N, F, G, H>,
146 branches: &Vec<Transform<N>>,
147) -> Result<Sequence<N>, Error> {
148 let mut result = vec![];
149 for b in branches {
150 let mut c = ctxt.dispatch(stctxt, b)?;
151 if c.iter().any(|f| !f.is_node()) {
152 return Err(Error::new(
153 ErrorKind::TypeError,
154 "all operands must be nodes",
155 ));
156 }
157 result.append(&mut c)
158 }
159 Ok(result)
161}