dsq_shared/ops/
arithmetic_ops.rs

1//! Arithmetic operations
2//!
3//! This module contains mathematical operations on numeric values.
4
5use crate::value::Value;
6use crate::Result;
7use std::any::Any;
8
9use super::traits::{Context, Operation};
10use super::utils::{add_values, div_values, mul_values, sub_values};
11
12/// Addition operation
13///
14/// Performs addition on numeric values or concatenation on strings/arrays.
15pub struct AddOperation {
16    /// Operations that produce the left operand
17    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
18    /// Operations that produce the right operand
19    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
20}
21
22impl AddOperation {
23    /// Creates a new addition operation with the given operand operations
24    pub fn new(
25        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
26        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
27    ) -> Self {
28        Self {
29            left_ops,
30            right_ops,
31        }
32    }
33}
34
35impl Operation for AddOperation {
36    fn apply(&self, value: &Value) -> Result<Value> {
37        let mut context = None;
38        self.apply_with_context(value, &mut context)
39    }
40
41    fn apply_with_context(
42        &self,
43        value: &Value,
44        context: &mut Option<&mut dyn Context>,
45    ) -> Result<Value> {
46        let mut left_val = value.clone();
47        for op in &self.left_ops {
48            left_val = op.apply_with_context(&left_val, context)?;
49        }
50
51        let mut right_val = value.clone();
52        for op in &self.right_ops {
53            right_val = op.apply_with_context(&right_val, context)?;
54        }
55
56        add_values(&left_val, &right_val)
57    }
58
59    fn description(&self) -> String {
60        "add".to_string()
61    }
62
63    fn as_any(&self) -> &dyn Any {
64        self
65    }
66}
67
68/// Subtraction operation
69///
70/// Performs subtraction on numeric values.
71pub struct SubOperation {
72    /// Operations that produce the left operand
73    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
74    /// Operations that produce the right operand
75    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
76}
77
78impl SubOperation {
79    /// Creates a new subtraction operation with the given operand operations
80    pub fn new(
81        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
82        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
83    ) -> Self {
84        Self {
85            left_ops,
86            right_ops,
87        }
88    }
89}
90
91impl Operation for SubOperation {
92    fn apply(&self, value: &Value) -> Result<Value> {
93        let mut context = None;
94        self.apply_with_context(value, &mut context)
95    }
96
97    fn apply_with_context(
98        &self,
99        value: &Value,
100        context: &mut Option<&mut dyn Context>,
101    ) -> Result<Value> {
102        let mut left_val = value.clone();
103        for op in &self.left_ops {
104            left_val = op.apply_with_context(&left_val, context)?;
105        }
106
107        let mut right_val = value.clone();
108        for op in &self.right_ops {
109            right_val = op.apply_with_context(&right_val, context)?;
110        }
111
112        sub_values(&left_val, &right_val)
113    }
114
115    fn description(&self) -> String {
116        "subtract".to_string()
117    }
118
119    fn as_any(&self) -> &dyn Any {
120        self
121    }
122}
123
124/// Multiplication operation
125///
126/// Performs multiplication on numeric values.
127pub struct MulOperation {
128    /// Operations that produce the left operand
129    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
130    /// Operations that produce the right operand
131    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
132}
133
134impl MulOperation {
135    /// Creates a new multiplication operation with the given operand operations
136    pub fn new(
137        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
138        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
139    ) -> Self {
140        Self {
141            left_ops,
142            right_ops,
143        }
144    }
145}
146
147impl Operation for MulOperation {
148    fn apply(&self, value: &Value) -> Result<Value> {
149        let mut context = None;
150        self.apply_with_context(value, &mut context)
151    }
152
153    fn apply_with_context(
154        &self,
155        value: &Value,
156        context: &mut Option<&mut dyn Context>,
157    ) -> Result<Value> {
158        let mut left_val = value.clone();
159        for op in &self.left_ops {
160            left_val = op.apply_with_context(&left_val, context)?;
161        }
162
163        let mut right_val = value.clone();
164        for op in &self.right_ops {
165            right_val = op.apply_with_context(&right_val, context)?;
166        }
167
168        mul_values(&left_val, &right_val)
169    }
170
171    fn description(&self) -> String {
172        "multiply".to_string()
173    }
174
175    fn as_any(&self) -> &dyn Any {
176        self
177    }
178}
179
180/// Division operation
181///
182/// Performs division on numeric values.
183pub struct DivOperation {
184    /// Operations that produce the left operand
185    pub left_ops: Vec<Box<dyn Operation + Send + Sync>>,
186    /// Operations that produce the right operand
187    pub right_ops: Vec<Box<dyn Operation + Send + Sync>>,
188}
189
190impl DivOperation {
191    /// Creates a new division operation with the given operand operations
192    pub fn new(
193        left_ops: Vec<Box<dyn Operation + Send + Sync>>,
194        right_ops: Vec<Box<dyn Operation + Send + Sync>>,
195    ) -> Self {
196        Self {
197            left_ops,
198            right_ops,
199        }
200    }
201}
202
203impl Operation for DivOperation {
204    fn apply(&self, value: &Value) -> Result<Value> {
205        let mut context = None;
206        self.apply_with_context(value, &mut context)
207    }
208
209    fn apply_with_context(
210        &self,
211        value: &Value,
212        context: &mut Option<&mut dyn Context>,
213    ) -> Result<Value> {
214        let mut left_val = value.clone();
215        for op in &self.left_ops {
216            left_val = op.apply_with_context(&left_val, context)?;
217        }
218
219        let mut right_val = value.clone();
220        for op in &self.right_ops {
221            right_val = op.apply_with_context(&right_val, context)?;
222        }
223
224        div_values(&left_val, &right_val)
225    }
226
227    fn description(&self) -> String {
228        "divide".to_string()
229    }
230
231    fn as_any(&self) -> &dyn Any {
232        self
233    }
234}