use crate::error::Result;
use crate::Value;
use super::Operation;
pub struct AndOperation {
pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
}
impl AndOperation {
#[must_use]
pub fn new(
left_ops: Vec<Box<dyn Operation + Send + Sync>>,
right_ops: Vec<Box<dyn Operation + Send + Sync>>,
) -> Self {
Self {
left_ops,
right_ops,
}
}
}
impl Operation for AndOperation {
fn apply(&self, value: &Value) -> Result<Value> {
let mut left_val = value.clone();
for op in &self.left_ops {
left_val = op.apply(&left_val)?;
}
let left_truthy = match left_val {
Value::Bool(b) => b,
Value::Int(i) if i != 0 => true,
Value::Float(f) if f != 0.0 => true,
Value::String(s) if !s.is_empty() => true,
Value::Array(arr) if !arr.is_empty() => true,
Value::Object(obj) if !obj.is_empty() => true,
_ => false,
};
if !left_truthy {
return Ok(Value::Bool(false));
}
let mut right_val = value.clone();
for op in &self.right_ops {
right_val = op.apply(&right_val)?;
}
let right_truthy = match right_val {
Value::Bool(b) => b,
Value::Int(i) if i != 0 => true,
Value::Float(f) if f != 0.0 => true,
Value::String(s) if !s.is_empty() => true,
Value::Array(arr) if !arr.is_empty() => true,
Value::Object(obj) if !obj.is_empty() => true,
_ => false,
};
Ok(Value::Bool(right_truthy))
}
fn description(&self) -> String {
"logical and".to_string()
}
}
pub struct OrOperation {
pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
}
impl OrOperation {
#[must_use]
pub fn new(
left_ops: Vec<Box<dyn Operation + Send + Sync>>,
right_ops: Vec<Box<dyn Operation + Send + Sync>>,
) -> Self {
Self {
left_ops,
right_ops,
}
}
}
impl Operation for OrOperation {
fn apply(&self, value: &Value) -> Result<Value> {
let mut left_val = value.clone();
for op in &self.left_ops {
left_val = op.apply(&left_val)?;
}
let left_truthy = match left_val {
Value::Bool(b) => b,
Value::Int(i) if i != 0 => true,
Value::Float(f) if f != 0.0 => true,
Value::String(s) if !s.is_empty() => true,
Value::Array(arr) if !arr.is_empty() => true,
Value::Object(obj) if !obj.is_empty() => true,
_ => false,
};
if left_truthy {
return Ok(Value::Bool(true));
}
let mut right_val = value.clone();
for op in &self.right_ops {
right_val = op.apply(&right_val)?;
}
let right_truthy = match right_val {
Value::Bool(b) => b,
Value::Int(i) if i != 0 => true,
Value::Float(f) if f != 0.0 => true,
Value::String(s) if !s.is_empty() => true,
Value::Array(arr) if !arr.is_empty() => true,
Value::Object(obj) if !obj.is_empty() => true,
_ => false,
};
Ok(Value::Bool(right_truthy))
}
fn description(&self) -> String {
"logical or".to_string()
}
}
pub struct NegationOperation {
pub expr_ops: Vec<Box<dyn Operation + Send + Sync>>,
}
impl NegationOperation {
#[must_use]
pub fn new(expr_ops: Vec<Box<dyn Operation + Send + Sync>>) -> Self {
Self { expr_ops }
}
}
impl Operation for NegationOperation {
fn apply(&self, value: &Value) -> Result<Value> {
let mut expr_val = value.clone();
for op in &self.expr_ops {
expr_val = op.apply(&expr_val)?;
}
let truthy = match expr_val {
Value::Bool(b) => b,
Value::Int(i) if i != 0 => true,
Value::Float(f) if f != 0.0 => true,
Value::String(s) if !s.is_empty() => true,
Value::Array(arr) if !arr.is_empty() => true,
Value::Object(obj) if !obj.is_empty() => true,
_ => false,
};
Ok(Value::Bool(!truthy))
}
fn description(&self) -> String {
"logical not".to_string()
}
}