use std::rc::Rc;
use url::Url;
use crate::item::{Item, Node, Sequence, SequenceTrait};
use crate::transform::Transform;
use crate::transform::context::{Context, StaticContext};
use crate::value::{Operator, Value};
use crate::xdmerror::{Error, ErrorKind};
pub(crate) fn tr_or<
N: Node,
F: FnMut(&str) -> Result<(), Error>,
G: FnMut(&str) -> Result<N, Error>,
H: FnMut(&Url) -> Result<String, Error>,
>(
ctxt: &Context<N>,
stctxt: &mut StaticContext<N, F, G, H>,
v: &Vec<Transform<N>>,
) -> Result<Sequence<N>, Error> {
let mut b = false;
let mut i = 0;
while let Some(a) = v.get(i) {
if ctxt.dispatch(stctxt, a)?.to_bool() {
b = true;
break;
}
i += 1;
}
Ok(vec![Item::Value(Rc::new(Value::from(b)))])
}
pub(crate) fn tr_and<
N: Node,
F: FnMut(&str) -> Result<(), Error>,
G: FnMut(&str) -> Result<N, Error>,
H: FnMut(&Url) -> Result<String, Error>,
>(
ctxt: &Context<N>,
stctxt: &mut StaticContext<N, F, G, H>,
v: &Vec<Transform<N>>,
) -> Result<Sequence<N>, Error> {
let mut b = true;
let mut i = 0;
while let Some(a) = v.get(i) {
if !ctxt.dispatch(stctxt, a)?.to_bool() {
b = false;
break;
}
i += 1;
}
Ok(vec![Item::Value(Rc::new(Value::from(b)))])
}
pub(crate) fn general_comparison<
N: Node,
F: FnMut(&str) -> Result<(), Error>,
G: FnMut(&str) -> Result<N, Error>,
H: FnMut(&Url) -> Result<String, Error>,
>(
ctxt: &Context<N>,
stctxt: &mut StaticContext<N, F, G, H>,
o: &Operator,
l: &Transform<N>,
r: &Transform<N>,
) -> Result<Sequence<N>, Error> {
let left = ctxt.dispatch(stctxt, l)?;
let right = ctxt.dispatch(stctxt, r)?;
let mut b = false;
for i in left {
for j in &right {
b = i.compare(j, *o)?;
if b {
break;
}
}
if b {
break;
}
}
Ok(vec![Item::Value(Rc::new(Value::from(b)))])
}
pub(crate) fn value_comparison<
N: Node,
F: FnMut(&str) -> Result<(), Error>,
G: FnMut(&str) -> Result<N, Error>,
H: FnMut(&Url) -> Result<String, Error>,
>(
ctxt: &Context<N>,
stctxt: &mut StaticContext<N, F, G, H>,
o: &Operator,
l: &Transform<N>,
r: &Transform<N>,
) -> Result<Sequence<N>, Error> {
let left = ctxt.dispatch(stctxt, l)?;
if left.len() != 1 {
return Err(Error::new(
ErrorKind::TypeError,
String::from("left-hand sequence is not a singleton sequence"),
));
}
let right = ctxt.dispatch(stctxt, r)?;
if right.len() != 1 {
return Err(Error::new(
ErrorKind::TypeError,
String::from("right-hand sequence is not a singleton sequence"),
));
}
Ok(vec![Item::Value(Rc::new(Value::from(
left[0].compare(&right[0], *o)?,
)))])
}
pub(crate) fn union<
N: Node,
F: FnMut(&str) -> Result<(), Error>,
G: FnMut(&str) -> Result<N, Error>,
H: FnMut(&Url) -> Result<String, Error>,
>(
ctxt: &Context<N>,
stctxt: &mut StaticContext<N, F, G, H>,
branches: &Vec<Transform<N>>,
) -> Result<Sequence<N>, Error> {
let mut result = vec![];
for b in branches {
let mut c = ctxt.dispatch(stctxt, b)?;
if c.iter().any(|f| !f.is_node()) {
return Err(Error::new(
ErrorKind::TypeError,
"all operands must be nodes",
));
}
result.append(&mut c)
}
Ok(result)
}