dsq_core/ops/
logical_ops.rs

1use crate::error::Result;
2use crate::Value;
3
4use super::Operation;
5
6pub struct AndOperation {
7    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
8    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
9}
10
11impl AndOperation {
12    #[must_use]
13    pub fn new(
14        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
15        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
16    ) -> Self {
17        Self {
18            left_ops,
19            right_ops,
20        }
21    }
22}
23
24impl Operation for AndOperation {
25    fn apply(&self, value: &Value) -> Result<Value> {
26        let mut left_val = value.clone();
27        for op in &self.left_ops {
28            left_val = op.apply(&left_val)?;
29        }
30
31        let left_truthy = match left_val {
32            Value::Bool(b) => b,
33            Value::Int(i) if i != 0 => true,
34            Value::Float(f) if f != 0.0 => true,
35            Value::String(s) if !s.is_empty() => true,
36            Value::Array(arr) if !arr.is_empty() => true,
37            Value::Object(obj) if !obj.is_empty() => true,
38            _ => false,
39        };
40
41        if !left_truthy {
42            return Ok(Value::Bool(false));
43        }
44
45        let mut right_val = value.clone();
46        for op in &self.right_ops {
47            right_val = op.apply(&right_val)?;
48        }
49
50        let right_truthy = match right_val {
51            Value::Bool(b) => b,
52            Value::Int(i) if i != 0 => true,
53            Value::Float(f) if f != 0.0 => true,
54            Value::String(s) if !s.is_empty() => true,
55            Value::Array(arr) if !arr.is_empty() => true,
56            Value::Object(obj) if !obj.is_empty() => true,
57            _ => false,
58        };
59
60        Ok(Value::Bool(right_truthy))
61    }
62
63    fn description(&self) -> String {
64        "logical and".to_string()
65    }
66}
67
68pub struct OrOperation {
69    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
70    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
71}
72
73impl OrOperation {
74    #[must_use]
75    pub fn new(
76        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
77        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
78    ) -> Self {
79        Self {
80            left_ops,
81            right_ops,
82        }
83    }
84}
85
86impl Operation for OrOperation {
87    fn apply(&self, value: &Value) -> Result<Value> {
88        let mut left_val = value.clone();
89        for op in &self.left_ops {
90            left_val = op.apply(&left_val)?;
91        }
92
93        let left_truthy = match left_val {
94            Value::Bool(b) => b,
95            Value::Int(i) if i != 0 => true,
96            Value::Float(f) if f != 0.0 => true,
97            Value::String(s) if !s.is_empty() => true,
98            Value::Array(arr) if !arr.is_empty() => true,
99            Value::Object(obj) if !obj.is_empty() => true,
100            _ => false,
101        };
102
103        if left_truthy {
104            return Ok(Value::Bool(true));
105        }
106
107        let mut right_val = value.clone();
108        for op in &self.right_ops {
109            right_val = op.apply(&right_val)?;
110        }
111
112        let right_truthy = match right_val {
113            Value::Bool(b) => b,
114            Value::Int(i) if i != 0 => true,
115            Value::Float(f) if f != 0.0 => true,
116            Value::String(s) if !s.is_empty() => true,
117            Value::Array(arr) if !arr.is_empty() => true,
118            Value::Object(obj) if !obj.is_empty() => true,
119            _ => false,
120        };
121
122        Ok(Value::Bool(right_truthy))
123    }
124
125    fn description(&self) -> String {
126        "logical or".to_string()
127    }
128}
129
130pub struct NegationOperation {
131    pub expr_ops: Vec<Box<dyn Operation + Send + Sync>>,
132}
133
134impl NegationOperation {
135    #[must_use]
136    pub fn new(expr_ops: Vec<Box<dyn Operation + Send + Sync>>) -> Self {
137        Self { expr_ops }
138    }
139}
140
141impl Operation for NegationOperation {
142    fn apply(&self, value: &Value) -> Result<Value> {
143        let mut expr_val = value.clone();
144        for op in &self.expr_ops {
145            expr_val = op.apply(&expr_val)?;
146        }
147
148        let truthy = match expr_val {
149            Value::Bool(b) => b,
150            Value::Int(i) if i != 0 => true,
151            Value::Float(f) if f != 0.0 => true,
152            Value::String(s) if !s.is_empty() => true,
153            Value::Array(arr) if !arr.is_empty() => true,
154            Value::Object(obj) if !obj.is_empty() => true,
155            _ => false,
156        };
157
158        Ok(Value::Bool(!truthy))
159    }
160
161    fn description(&self) -> String {
162        "logical not".to_string()
163    }
164}