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}