dsq_shared/ops/
construct_ops.rs1use crate::value::Value;
6use crate::Result;
7use std::any::Any;
8
9use super::traits::{Context, Operation};
10
11type FieldOpPair = (
13 Box<dyn Operation + Send + Sync>,
14 Option<Vec<Box<dyn Operation + Send + Sync>>>,
15);
16
17pub struct ObjectConstructOperation {
21 pub field_ops: Vec<FieldOpPair>,
27}
28
29impl ObjectConstructOperation {
30 pub fn new(field_ops: Vec<FieldOpPair>) -> Self {
32 Self { field_ops }
33 }
34}
35
36impl Operation for ObjectConstructOperation {
37 fn apply(&self, value: &Value) -> Result<Value> {
38 let mut context = None;
39 self.apply_with_context(value, &mut context)
40 }
41
42 fn apply_with_context(
43 &self,
44 value: &Value,
45 context: &mut Option<&mut dyn Context>,
46 ) -> Result<Value> {
47 if matches!(value, Value::Null) {
49 return Ok(Value::Null);
50 }
51
52 let mut obj = std::collections::HashMap::new();
54
55 for (key_op, value_op) in &self.field_ops {
56 let key_value = key_op.apply_with_context(value, context)?;
57 let key = match key_value {
58 Value::String(s) => s,
59 _ => return Err(crate::error::operation_error("Object key must be a string")),
60 };
61
62 let field_value = if let Some(ops) = value_op {
63 let mut current = value.clone();
64 for op in ops {
65 current = op.apply_with_context(¤t, context)?;
66 }
67 current
68 } else {
69 value.field(&key)?
71 };
72
73 obj.insert(key, field_value);
74 }
75
76 Ok(Value::Object(obj))
77 }
78
79 fn description(&self) -> String {
80 "object construction".to_string()
81 }
82
83 fn as_any(&self) -> &dyn Any {
84 self
85 }
86}
87
88pub struct ArrayConstructOperation {
92 pub element_ops: Vec<Box<dyn Operation + Send + Sync>>,
94}
95
96impl ArrayConstructOperation {
97 pub fn new(element_ops: Vec<Box<dyn Operation + Send + Sync>>) -> Self {
99 Self { element_ops }
100 }
101}
102
103impl Operation for ArrayConstructOperation {
104 fn apply(&self, value: &Value) -> Result<Value> {
105 let mut context = None;
106 self.apply_with_context(value, &mut context)
107 }
108
109 fn apply_with_context(
110 &self,
111 value: &Value,
112 context: &mut Option<&mut dyn Context>,
113 ) -> Result<Value> {
114 let mut arr = Vec::new();
115 for op in &self.element_ops {
116 arr.push(op.apply_with_context(value, context)?);
117 }
118 Ok(Value::Array(arr))
119 }
120
121 fn description(&self) -> String {
122 "array construction".to_string()
123 }
124
125 fn as_any(&self) -> &dyn Any {
126 self
127 }
128}
129
130pub struct SequenceOperation {
134 pub expr_ops: Vec<Vec<Box<dyn Operation + Send + Sync>>>,
136}
137
138impl SequenceOperation {
139 pub fn new(expr_ops: Vec<Vec<Box<dyn Operation + Send + Sync>>>) -> Self {
141 Self { expr_ops }
142 }
143}
144
145impl Operation for SequenceOperation {
146 fn apply(&self, value: &Value) -> Result<Value> {
147 let mut context = None;
148 self.apply_with_context(value, &mut context)
149 }
150
151 fn apply_with_context(
152 &self,
153 value: &Value,
154 context: &mut Option<&mut dyn Context>,
155 ) -> Result<Value> {
156 let mut results = Vec::new();
157 for ops in &self.expr_ops {
158 let mut val = value.clone();
159 for op in ops {
160 val = op.apply_with_context(&val, context)?;
161 }
162 results.push(val);
163 }
164 Ok(Value::Array(results))
165 }
166
167 fn description(&self) -> String {
168 "sequence".to_string()
169 }
170
171 fn as_any(&self) -> &dyn Any {
172 self
173 }
174}