toasty_core/stmt/
assignments.rs1use crate::stmt::Statement;
2
3use super::{Expr, Projection};
4
5use indexmap::{Equivalent, IndexMap};
6use std::{hash::Hash, ops};
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct Assignments {
10 assignments: IndexMap<Projection, Assignment>,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct Assignment {
19 pub op: AssignmentOp,
21
22 pub expr: Expr,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq)]
27pub enum AssignmentOp {
28 Set,
30
31 Insert,
33
34 Remove,
36}
37
38impl Statement {
39 pub fn assignments(&self) -> Option<&Assignments> {
40 match self {
41 Statement::Update(update) => Some(&update.assignments),
42 _ => None,
43 }
44 }
45}
46
47impl Assignments {
48 pub fn with_capacity(capacity: usize) -> Self {
49 Self {
50 assignments: IndexMap::with_capacity(capacity),
51 }
52 }
53
54 pub fn is_empty(&self) -> bool {
55 self.assignments.is_empty()
56 }
57
58 pub fn len(&self) -> usize {
59 self.assignments.len()
60 }
61
62 pub fn contains<Q>(&self, key: &Q) -> bool
63 where
64 Q: ?Sized + Hash + Equivalent<Projection>,
65 {
66 self.assignments.contains_key(key)
67 }
68
69 pub fn get<Q>(&self, key: &Q) -> Option<&Assignment>
70 where
71 Q: ?Sized + Hash + Equivalent<Projection>,
72 {
73 self.assignments.get(key)
74 }
75
76 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut Assignment>
77 where
78 Q: ?Sized + Hash + Equivalent<Projection>,
79 {
80 self.assignments.get_mut(key)
81 }
82
83 pub fn set<Q>(&mut self, key: Q, expr: impl Into<Expr>)
84 where
85 Q: Into<Projection>,
86 {
87 let key = key.into();
88 self.assignments.insert(
89 key,
90 Assignment {
91 op: AssignmentOp::Set,
92 expr: expr.into(),
93 },
94 );
95 }
96
97 pub fn unset<Q>(&mut self, key: &Q)
98 where
99 Q: ?Sized + Hash + Equivalent<Projection>,
100 {
101 self.assignments.swap_remove(key);
102 }
103
104 pub fn insert<Q>(&mut self, key: Q, expr: impl Into<Expr>)
107 where
108 Q: Into<Projection>,
109 {
110 use indexmap::map::Entry;
111
112 let key = key.into();
113 match self.assignments.entry(key) {
114 Entry::Occupied(_) => {
115 todo!()
116 }
117 Entry::Vacant(entry) => {
118 entry.insert(Assignment {
119 op: AssignmentOp::Insert,
120 expr: expr.into(),
121 });
122 }
123 }
124 }
125
126 pub fn remove<Q>(&mut self, key: Q, expr: impl Into<Expr>)
127 where
128 Q: Into<Projection>,
129 {
130 use indexmap::map::Entry;
131
132 let key = key.into();
133 match self.assignments.entry(key) {
134 Entry::Occupied(_) => {
135 todo!()
136 }
137 Entry::Vacant(entry) => {
138 entry.insert(Assignment {
139 op: AssignmentOp::Remove,
140 expr: expr.into(),
141 });
142 }
143 }
144 }
145
146 pub fn take<Q>(&mut self, key: &Q) -> Option<Assignment>
147 where
148 Q: ?Sized + Hash + Equivalent<Projection>,
149 {
150 self.assignments.swap_remove(key)
151 }
152
153 pub fn keys(&self) -> impl Iterator<Item = &Projection> + '_ {
154 self.assignments.keys()
155 }
156
157 pub fn exprs(&self) -> impl Iterator<Item = &Expr> + '_ {
158 self.assignments.values().map(|assignment| &assignment.expr)
159 }
160
161 pub fn iter(&self) -> impl Iterator<Item = (&Projection, &Assignment)> + '_ {
162 self.assignments.iter()
163 }
164
165 pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Projection, &mut Assignment)> + '_ {
166 self.assignments.iter_mut()
167 }
168}
169
170impl IntoIterator for Assignments {
171 type Item = (Projection, Assignment);
172 type IntoIter = indexmap::map::IntoIter<Projection, Assignment>;
173
174 fn into_iter(self) -> Self::IntoIter {
175 self.assignments.into_iter()
176 }
177}
178
179impl<'a> IntoIterator for &'a Assignments {
180 type Item = (&'a Projection, &'a Assignment);
181 type IntoIter = indexmap::map::Iter<'a, Projection, Assignment>;
182
183 fn into_iter(self) -> Self::IntoIter {
184 self.assignments.iter()
185 }
186}
187
188impl Default for Assignments {
189 fn default() -> Self {
190 Self {
191 assignments: IndexMap::new(),
192 }
193 }
194}
195
196impl<Q> ops::Index<Q> for Assignments
197where
198 Q: Hash + Equivalent<Projection>,
199{
200 type Output = Assignment;
201
202 fn index(&self, index: Q) -> &Self::Output {
203 match self.assignments.get(&index) {
204 Some(ret) => ret,
205 None => panic!("no assignment for projection"),
206 }
207 }
208}
209
210impl<Q> ops::IndexMut<Q> for Assignments
211where
212 Q: Hash + Equivalent<Projection>,
213{
214 fn index_mut(&mut self, index: Q) -> &mut Self::Output {
215 match self.assignments.get_mut(&index) {
216 Some(ret) => ret,
217 None => panic!("no assignment for projection"),
218 }
219 }
220}
221
222impl AssignmentOp {
223 pub fn is_set(self) -> bool {
224 matches!(self, Self::Set)
225 }
226
227 pub fn is_remove(self) -> bool {
228 matches!(self, Self::Remove)
229 }
230}