toasty_core/stmt/entry_mut.rs
1use super::{Expr, Value};
2
3/// A mutable reference to either an [`Expr`] or a [`Value`] within a
4/// composite structure.
5///
6/// This is the mutable counterpart to [`Entry`](super::Entry), used for
7/// in-place modification of nested expressions or values.
8///
9/// # Examples
10///
11/// ```ignore
12/// use toasty_core::stmt::{EntryMut, Expr, Value};
13///
14/// let mut expr = Expr::from(Value::from(42_i64));
15/// let mut entry = EntryMut::from(&mut expr);
16/// assert!(entry.is_expr());
17/// ```
18#[derive(Debug)]
19pub enum EntryMut<'a> {
20 /// A mutable reference to an expression.
21 Expr(&'a mut Expr),
22 /// A mutable reference to a value.
23 Value(&'a mut Value),
24}
25
26impl EntryMut<'_> {
27 /// Returns a reference to the contained expression, or `None`.
28 pub fn as_expr(&self) -> Option<&Expr> {
29 match self {
30 EntryMut::Expr(e) => Some(e),
31 _ => None,
32 }
33 }
34
35 /// Returns a reference to the contained expression, panicking if not an expression.
36 ///
37 /// # Panics
38 ///
39 /// Panics if this entry is not `EntryMut::Expr`.
40 #[track_caller]
41 pub fn as_expr_unwrap(&self) -> &Expr {
42 self.as_expr()
43 .unwrap_or_else(|| panic!("expected EntryMut::Expr; actual={self:#?}"))
44 }
45
46 /// Returns a mutable reference to the contained expression, or `None`.
47 pub fn as_expr_mut(&mut self) -> Option<&mut Expr> {
48 match self {
49 EntryMut::Expr(e) => Some(e),
50 _ => None,
51 }
52 }
53
54 /// Returns a mutable reference to the contained expression, panicking if not an expression.
55 ///
56 /// # Panics
57 ///
58 /// Panics if this entry is not `EntryMut::Expr`.
59 #[track_caller]
60 pub fn as_expr_mut_unwrap(&mut self) -> &mut Expr {
61 match self {
62 EntryMut::Expr(e) => e,
63 _ => panic!("expected EntryMut::Expr"),
64 }
65 }
66
67 /// Returns `true` if this entry holds an expression.
68 pub fn is_expr(&self) -> bool {
69 matches!(self, EntryMut::Expr(_))
70 }
71
72 /// Returns `true` if this entry holds a statement expression.
73 pub fn is_statement(&self) -> bool {
74 matches!(self, EntryMut::Expr(e) if e.is_stmt())
75 }
76
77 /// Returns `true` if this entry holds a concrete value.
78 pub fn is_value(&self) -> bool {
79 matches!(self, EntryMut::Value(_) | EntryMut::Expr(Expr::Value(_)))
80 }
81
82 /// Returns `true` if this entry holds a null value.
83 pub fn is_value_null(&self) -> bool {
84 matches!(
85 self,
86 EntryMut::Value(Value::Null) | EntryMut::Expr(Expr::Value(Value::Null))
87 )
88 }
89
90 /// Returns `true` if this entry holds a record, either as an
91 /// `Expr::Record`, an `Expr::Value(Value::Record)`, or a bare
92 /// `Value::Record`.
93 pub fn is_record(&self) -> bool {
94 match self {
95 EntryMut::Expr(Expr::Record(_)) => true,
96 EntryMut::Expr(Expr::Value(value)) => value.is_record(),
97 EntryMut::Value(value) => value.is_record(),
98 EntryMut::Expr(_) => false,
99 }
100 }
101
102 /// Returns `true` if this entry is `Expr::Default`.
103 pub fn is_default(&self) -> bool {
104 matches!(self, EntryMut::Expr(Expr::Default))
105 }
106
107 /// Takes the contained expression or value, replacing it with a default.
108 pub fn take(&mut self) -> Expr {
109 match self {
110 EntryMut::Expr(expr) => expr.take(),
111 EntryMut::Value(value) => value.take().into(),
112 }
113 }
114
115 /// Replaces the contents of this entry with `expr`.
116 ///
117 /// # Panics
118 ///
119 /// Panics if this is a `Value` entry and `expr` is not `Expr::Value`.
120 pub fn insert(&mut self, expr: Expr) {
121 match self {
122 EntryMut::Expr(e) => **e = expr,
123 EntryMut::Value(e) => match expr {
124 Expr::Value(value) => **e = value,
125 _ => panic!("cannot store expression in value entry"),
126 },
127 }
128 }
129}
130
131impl<'a> From<&'a mut Expr> for EntryMut<'a> {
132 fn from(value: &'a mut Expr) -> Self {
133 EntryMut::Expr(value)
134 }
135}
136
137impl<'a> From<&'a mut Value> for EntryMut<'a> {
138 fn from(value: &'a mut Value) -> Self {
139 EntryMut::Value(value)
140 }
141}