use crate::error::Result;
use crate::Value;
use super::Operation;
pub struct LiteralOperation {
pub value: Value,
}
impl LiteralOperation {
#[must_use]
pub fn new(value: Value) -> Self {
Self { value }
}
}
impl Operation for LiteralOperation {
fn apply(&self, _value: &Value) -> Result<Value> {
Ok(self.value.clone())
}
fn description(&self) -> String {
format!("literal: {:?}", self.value)
}
}
pub struct VariableOperation {
pub name: String,
}
impl VariableOperation {
#[must_use]
pub fn new(name: String) -> Self {
Self { name }
}
}
impl Operation for VariableOperation {
fn apply(&self, _value: &Value) -> Result<Value> {
Err(crate::error::Error::operation(format!(
"Variable '{}' not found",
self.name
)))
}
fn description(&self) -> String {
format!("variable: {}", self.name)
}
}
#[allow(clippy::type_complexity)]
pub struct ObjectConstructOperation {
pub field_ops: Vec<(
Box<dyn Operation + Send + Sync>,
Option<Vec<Box<dyn Operation + Send + Sync>>>,
)>,
}
impl ObjectConstructOperation {
#[must_use]
#[allow(clippy::type_complexity)]
pub fn new(
field_ops: Vec<(
Box<dyn Operation + Send + Sync>,
Option<Vec<Box<dyn Operation + Send + Sync>>>,
)>,
) -> Self {
Self { field_ops }
}
}
impl Operation for ObjectConstructOperation {
fn apply(&self, value: &Value) -> Result<Value> {
let mut obj = std::collections::HashMap::new();
for (key_op, value_op) in &self.field_ops {
let key_value = key_op.apply(value)?;
let Value::String(key) = key_value else {
return Err(crate::error::Error::operation(
"Object key must be a string",
));
};
let field_value = if let Some(ref ops) = value_op {
let mut current = value.clone();
for op in ops {
current = op.apply(¤t)?;
}
current
} else {
value.field(&key)?
};
obj.insert(key, field_value);
}
Ok(Value::Object(obj))
}
fn description(&self) -> String {
"object construction".to_string()
}
}
pub struct ArrayConstructOperation {
pub element_ops: Vec<Box<dyn Operation + Send + Sync>>,
}
impl ArrayConstructOperation {
#[must_use]
pub fn new(element_ops: Vec<Box<dyn Operation + Send + Sync>>) -> Self {
Self { element_ops }
}
}
impl Operation for ArrayConstructOperation {
fn apply(&self, value: &Value) -> Result<Value> {
let mut arr = Vec::new();
for op in &self.element_ops {
arr.push(op.apply(value)?);
}
Ok(Value::Array(arr))
}
fn description(&self) -> String {
"array construction".to_string()
}
}