dsq_core/ops/
construct_ops.rs

1use crate::error::Result;
2use crate::Value;
3
4use super::Operation;
5
6/// Literal value operation
7pub struct LiteralOperation {
8    pub value: Value,
9}
10
11impl LiteralOperation {
12    #[must_use]
13    pub fn new(value: Value) -> Self {
14        Self { value }
15    }
16}
17
18impl Operation for LiteralOperation {
19    fn apply(&self, _value: &Value) -> Result<Value> {
20        Ok(self.value.clone())
21    }
22
23    fn description(&self) -> String {
24        format!("literal: {:?}", self.value)
25    }
26}
27
28/// Variable access operation
29pub struct VariableOperation {
30    pub name: String,
31}
32
33impl VariableOperation {
34    #[must_use]
35    pub fn new(name: String) -> Self {
36        Self { name }
37    }
38}
39
40impl Operation for VariableOperation {
41    fn apply(&self, _value: &Value) -> Result<Value> {
42        // For now, variables are not supported
43        Err(crate::error::Error::operation(format!(
44            "Variable '{}' not found",
45            self.name
46        )))
47    }
48
49    fn description(&self) -> String {
50        format!("variable: {}", self.name)
51    }
52}
53
54/// Object construction operation
55#[allow(clippy::type_complexity)]
56pub struct ObjectConstructOperation {
57    pub field_ops: Vec<(
58        Box<dyn Operation + Send + Sync>,
59        Option<Vec<Box<dyn Operation + Send + Sync>>>,
60    )>,
61}
62
63impl ObjectConstructOperation {
64    #[must_use]
65    #[allow(clippy::type_complexity)]
66    pub fn new(
67        field_ops: Vec<(
68            Box<dyn Operation + Send + Sync>,
69            Option<Vec<Box<dyn Operation + Send + Sync>>>,
70        )>,
71    ) -> Self {
72        Self { field_ops }
73    }
74}
75
76impl Operation for ObjectConstructOperation {
77    fn apply(&self, value: &Value) -> Result<Value> {
78        let mut obj = std::collections::HashMap::new();
79
80        for (key_op, value_op) in &self.field_ops {
81            let key_value = key_op.apply(value)?;
82            let Value::String(key) = key_value else {
83                return Err(crate::error::Error::operation(
84                    "Object key must be a string",
85                ));
86            };
87
88            let field_value = if let Some(ref ops) = value_op {
89                let mut current = value.clone();
90                for op in ops {
91                    current = op.apply(&current)?;
92                }
93                current
94            } else {
95                // Shorthand: use the key as a field access
96                value.field(&key)?
97            };
98
99            obj.insert(key, field_value);
100        }
101
102        Ok(Value::Object(obj))
103    }
104
105    fn description(&self) -> String {
106        "object construction".to_string()
107    }
108}
109
110/// Array construction operation
111pub struct ArrayConstructOperation {
112    pub element_ops: Vec<Box<dyn Operation + Send + Sync>>,
113}
114
115impl ArrayConstructOperation {
116    #[must_use]
117    pub fn new(element_ops: Vec<Box<dyn Operation + Send + Sync>>) -> Self {
118        Self { element_ops }
119    }
120}
121
122impl Operation for ArrayConstructOperation {
123    fn apply(&self, value: &Value) -> Result<Value> {
124        let mut arr = Vec::new();
125        for op in &self.element_ops {
126            arr.push(op.apply(value)?);
127        }
128        Ok(Value::Array(arr))
129    }
130
131    fn description(&self) -> String {
132        "array construction".to_string()
133    }
134}