toasty_core/stmt/
entry.rs

1use crate::Result;
2
3use super::{Expr, Input, Value};
4
5#[derive(Debug)]
6pub enum Entry<'a> {
7    Expr(&'a Expr),
8    Value(&'a Value),
9}
10
11impl Entry<'_> {
12    /// Evaluates the entry to a value using the provided input.
13    ///
14    /// For `Entry::Expr`, evaluates the expression with the given input context.
15    /// For `Entry::Value`, returns a clone of the value directly.
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// # use toasty_core::stmt::{Entry, Value, ConstInput};
21    /// let value = Value::from(42);
22    /// let entry = Entry::from(&value);
23    ///
24    /// let result = entry.eval(ConstInput::new()).unwrap();
25    /// assert_eq!(result, Value::from(42));
26    /// ```
27    pub fn eval(&self, input: impl Input) -> Result<Value> {
28        match self {
29            Entry::Expr(expr) => expr.eval(input),
30            Entry::Value(value) => Ok((*value).clone()),
31        }
32    }
33
34    /// Evaluates the entry as a constant expression.
35    ///
36    /// For `Entry::Expr`, attempts to evaluate the expression without any input context.
37    /// This only succeeds if the expression is constant (contains no references or arguments).
38    /// For `Entry::Value`, returns a clone of the value directly.
39    ///
40    /// # Errors
41    ///
42    /// Returns an error if the entry contains an expression that cannot be evaluated
43    /// as a constant (e.g., references to columns or arguments).
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// # use toasty_core::stmt::{Entry, Value};
49    /// let value = Value::from("hello");
50    /// let entry = Entry::from(&value);
51    ///
52    /// let result = entry.eval_const().unwrap();
53    /// assert_eq!(result, Value::from("hello"));
54    /// ```
55    pub fn eval_const(&self) -> Result<Value> {
56        match self {
57            Entry::Expr(expr) => expr.eval_const(),
58            Entry::Value(value) => Ok((*value).clone()),
59        }
60    }
61
62    /// Returns `true` if the entry is a constant expression.
63    ///
64    /// An entry is considered constant if it does not reference any external data:
65    /// - `Entry::Value` is always constant
66    /// - `Entry::Expr` is constant if the expression itself is constant
67    ///   (see [`Expr::is_const`] for details)
68    ///
69    /// Constant entries can be evaluated without any input context.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// # use toasty_core::stmt::{Entry, Value, Expr};
75    /// // Values are always constant
76    /// let value = Value::from(42);
77    /// let entry = Entry::from(&value);
78    /// assert!(entry.is_const());
79    ///
80    /// // Constant expressions
81    /// let expr = Expr::from(Value::from("hello"));
82    /// let entry = Entry::from(&expr);
83    /// assert!(entry.is_const());
84    /// ```
85    pub fn is_const(&self) -> bool {
86        match self {
87            Entry::Value(_) => true,
88            Entry::Expr(expr) => expr.is_const(),
89        }
90    }
91
92    pub fn is_expr(&self) -> bool {
93        matches!(self, Entry::Expr(_))
94    }
95
96    pub fn to_expr(&self) -> Expr {
97        match *self {
98            Entry::Expr(expr) => expr.clone(),
99            Entry::Value(value) => value.clone().into(),
100        }
101    }
102
103    pub fn is_expr_default(&self) -> bool {
104        matches!(self, Entry::Expr(Expr::Default))
105    }
106
107    pub fn is_value(&self) -> bool {
108        matches!(self, Entry::Value(_) | Entry::Expr(Expr::Value(_)))
109    }
110
111    pub fn is_value_null(&self) -> bool {
112        matches!(
113            self,
114            Entry::Value(Value::Null) | Entry::Expr(Expr::Value(Value::Null))
115        )
116    }
117
118    pub fn try_as_value(&self) -> Option<&Value> {
119        match *self {
120            Entry::Expr(Expr::Value(value)) | Entry::Value(value) => Some(value),
121            _ => None,
122        }
123    }
124
125    pub fn as_value(&self) -> &Value {
126        match *self {
127            Entry::Expr(Expr::Value(value)) | Entry::Value(value) => value,
128            _ => todo!(),
129        }
130    }
131
132    pub fn to_value(&self) -> Value {
133        match *self {
134            Entry::Expr(Expr::Value(value)) | Entry::Value(value) => value.clone(),
135            Entry::Expr(expr) => expr.eval_const().unwrap_or_else(|err| {
136                panic!("not const expression; entry={self:#?}; error={err:#?}")
137            }),
138        }
139    }
140}
141
142impl<'a> From<&'a Expr> for Entry<'a> {
143    fn from(value: &'a Expr) -> Self {
144        Entry::Expr(value)
145    }
146}
147
148impl<'a> From<&'a Value> for Entry<'a> {
149    fn from(value: &'a Value) -> Self {
150        Entry::Value(value)
151    }
152}
153
154impl<'a> From<Entry<'a>> for Expr {
155    fn from(value: Entry<'a>) -> Self {
156        match value {
157            Entry::Expr(expr) => expr.clone(),
158            Entry::Value(value) => value.clone().into(),
159        }
160    }
161}