use std::fmt;
use crate::{Value, Result};
use crate::result::ValueError;
use crate::expressions::Expression;
use crate::{Evaluation, Nodeset};
pub trait Function: fmt::Debug {
fn exec(&self, eval: &Evaluation) -> Result<Value>;
}
#[derive(Debug, Clone)]
pub struct Last;
impl Function for Last {
fn exec(&self, eval: &Evaluation) -> Result<Value> {
Ok(Value::Number(eval.size as f64))
}
}
#[derive(Debug, Clone)]
pub struct Position;
impl Function for Position {
fn exec(&self, eval: &Evaluation) -> Result<Value> {
Ok(Value::Number(eval.position as f64))
}
}
#[derive(Debug, Clone)]
pub struct Count(Nodeset);
impl Function for Count {
fn exec(&self, _context: &Evaluation) -> Result<Value> {
Ok(Value::Number(self.0.nodes.len() as f64))
}
}
#[derive(Debug)]
pub struct Contains(Box<dyn Expression>, Value);
impl Contains {
pub fn new(left: Box<dyn Expression>, right: Value) -> Self {
Contains(left, right)
}
}
impl Function for Contains {
fn exec(&self, eval: &Evaluation) -> Result<Value> {
let value = self.1.as_string()?;
let found = self.0.eval(eval)?.into_nodeset()?;
if let Some(node) = found.into_iter().next() {
let node_value = node.value()?.string()?;
Ok(Value::Boolean(node_value.contains(value)))
} else {
Ok(Value::Boolean(false))
}
}
}
#[derive(Debug)]
pub struct Not(Box<dyn Expression>);
impl Not {
pub fn new(value: Box<dyn Expression>) -> Self {
Not(value)
}
}
impl Function for Not {
fn exec(&self, eval: &Evaluation) -> Result<Value> {
let found = self.0.eval(eval)?;
Ok(Value::Boolean(!found.boolean()?))
}
}
#[derive(Debug)]
pub struct True;
impl Function for True {
fn exec(&self, _: &Evaluation) -> Result<Value> {
Ok(Value::Boolean(true))
}
}
#[derive(Debug)]
pub struct False;
impl Function for False {
fn exec(&self, _: &Evaluation) -> Result<Value> {
Ok(Value::Boolean(false))
}
}
#[derive(Debug, Clone)]
pub struct Sum(Value);
impl Function for Sum {
fn exec(&self, _context: &Evaluation) -> Result<Value> {
let node_set = self.0.as_nodeset()?;
let orig_len = node_set.len();
let values = node_set.nodes.iter()
.map(|n| n.value().and_then(|v| v.number()))
.collect::<Result<Vec<f64>>>()?;
if orig_len != values.len() {
return Err(ValueError::Number.into());
}
Ok(Value::Number(values.into_iter().sum()))
}
}
#[derive(Debug, Clone)]
pub struct Floor(Value);
impl Function for Floor {
fn exec(&self, _context: &Evaluation) -> Result<Value> {
let val = self.0.number()?;
Ok(Value::Number(val.floor()))
}
}
#[derive(Debug, Clone)]
pub struct Ceiling(Value);
impl Function for Ceiling {
fn exec(&self, _context: &Evaluation) -> Result<Value> {
let val = self.0.number()?;
Ok(Value::Number(val.ceil()))
}
}
#[derive(Debug, Clone)]
pub struct Round(Value);
impl Function for Round {
fn exec(&self, _context: &Evaluation) -> Result<Value> {
let val = self.0.number()?;
Ok(Value::Number(val.round()))
}
}