1use serde::{Deserialize, Deserializer, Serialize, Serializer};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(untagged)]
15pub enum AssignmentTargets<E = super::Expr> {
16 Single(AssignmentTarget<E>),
17 Multiple(MultipleAssignmentTargets<E>),
18}
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct MultipleAssignmentTargets<E> {
23 pub targets: Vec<AssignmentTarget<E>>,
24 pub source_positions: Vec<usize>,
25 pub source_width: usize,
26}
27
28impl<E> From<Vec<AssignmentTarget<E>>> for MultipleAssignmentTargets<E> {
29 fn from(targets: Vec<AssignmentTarget<E>>) -> Self {
30 Self {
31 source_positions: (0..targets.len()).collect(),
32 source_width: targets.len(),
33 targets,
34 }
35 }
36}
37
38impl<E> From<AssignmentTarget<E>> for AssignmentTargets<E> {
39 fn from(target: AssignmentTarget<E>) -> Self {
40 Self::Single(target)
41 }
42}
43
44impl<E> From<String> for AssignmentTargets<E> {
45 fn from(column: String) -> Self {
46 Self::Single(column.into())
47 }
48}
49
50impl<E> From<&str> for AssignmentTargets<E> {
51 fn from(column: &str) -> Self {
52 column.to_owned().into()
53 }
54}
55
56impl<E> AssignmentTargets<E> {
57 pub fn targets(&self) -> &[AssignmentTarget<E>] {
58 match self {
59 Self::Single(target) => std::slice::from_ref(target),
60 Self::Multiple(group) => &group.targets,
61 }
62 }
63
64 pub fn targets_mut(&mut self) -> &mut [AssignmentTarget<E>] {
65 match self {
66 Self::Single(target) => std::slice::from_mut(target),
67 Self::Multiple(group) => &mut group.targets,
68 }
69 }
70
71 pub fn source_position(&self, target: usize) -> usize {
72 match self {
73 Self::Single(_) => target,
74 Self::Multiple(group) => group.source_positions[target],
75 }
76 }
77
78 pub fn column_names(&self) -> impl Iterator<Item = &str> {
79 self.targets().iter().map(|target| target.column.as_str())
80 }
81
82 pub fn expressions(&self) -> impl Iterator<Item = &E> {
83 self.targets()
84 .iter()
85 .flat_map(AssignmentTarget::expressions)
86 }
87
88 pub fn expressions_mut(&mut self) -> impl Iterator<Item = &mut E> {
89 self.targets_mut()
90 .iter_mut()
91 .flat_map(AssignmentTarget::expressions_mut)
92 }
93
94 pub fn map<T>(self, mut map: impl FnMut(E) -> T) -> AssignmentTargets<T> {
95 match self {
96 Self::Single(target) => AssignmentTargets::Single(target.map(map)),
97 Self::Multiple(group) => AssignmentTargets::Multiple(MultipleAssignmentTargets {
98 targets: group
99 .targets
100 .into_iter()
101 .map(|target| target.map(&mut map))
102 .collect(),
103 source_positions: group.source_positions,
104 source_width: group.source_width,
105 }),
106 }
107 }
108}
109
110#[derive(Debug, Clone, PartialEq)]
112pub struct AssignmentTarget<E = super::Expr> {
113 pub column: String,
114 pub indirection: Vec<AssignmentStep<E>>,
115}
116
117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
118pub enum AssignmentStep<E> {
119 Field(String),
120 Index(Box<E>),
121 Slice {
122 lower: Option<Box<E>>,
123 upper: Option<Box<E>>,
124 },
125}
126
127impl<E> From<String> for AssignmentTarget<E> {
128 fn from(column: String) -> Self {
129 Self {
130 column,
131 indirection: Vec::new(),
132 }
133 }
134}
135
136impl<E> From<&str> for AssignmentTarget<E> {
137 fn from(column: &str) -> Self {
138 column.to_owned().into()
139 }
140}
141
142impl<E> AssignmentTarget<E> {
143 pub fn is_whole_column(&self) -> bool {
144 self.indirection.is_empty()
145 }
146
147 pub fn expressions(&self) -> impl Iterator<Item = &E> {
148 self.indirection.iter().flat_map(|step| {
149 match step {
150 AssignmentStep::Field(_) => [None, None],
151 AssignmentStep::Index(index) => [Some(index.as_ref()), None],
152 AssignmentStep::Slice { lower, upper } => [lower.as_deref(), upper.as_deref()],
153 }
154 .into_iter()
155 .flatten()
156 })
157 }
158
159 pub fn expressions_mut(&mut self) -> impl Iterator<Item = &mut E> {
160 self.indirection.iter_mut().flat_map(|step| {
161 match step {
162 AssignmentStep::Field(_) => [None, None],
163 AssignmentStep::Index(index) => [Some(index.as_mut()), None],
164 AssignmentStep::Slice { lower, upper } => {
165 [lower.as_deref_mut(), upper.as_deref_mut()]
166 }
167 }
168 .into_iter()
169 .flatten()
170 })
171 }
172
173 pub fn map<T>(self, mut map: impl FnMut(E) -> T) -> AssignmentTarget<T> {
174 AssignmentTarget {
175 column: self.column,
176 indirection: self
177 .indirection
178 .into_iter()
179 .map(|step| match step {
180 AssignmentStep::Field(field) => AssignmentStep::Field(field),
181 AssignmentStep::Index(index) => AssignmentStep::Index(Box::new(map(*index))),
182 AssignmentStep::Slice { lower, upper } => AssignmentStep::Slice {
183 lower: lower.map(|value| Box::new(map(*value))),
184 upper: upper.map(|value| Box::new(map(*value))),
185 },
186 })
187 .collect(),
188 }
189 }
190}
191
192impl<E: Serialize> Serialize for AssignmentTarget<E> {
193 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
194 #[derive(Serialize)]
195 #[serde(untagged)]
196 enum Target<'a, E> {
197 Column(&'a str),
198 Partial {
199 column: &'a str,
200 indirection: &'a [AssignmentStep<E>],
201 },
202 }
203 if self.is_whole_column() {
204 Target::<E>::Column(&self.column).serialize(serializer)
205 } else {
206 Target::Partial {
207 column: &self.column,
208 indirection: &self.indirection,
209 }
210 .serialize(serializer)
211 }
212 }
213}
214
215impl<'de, E: Deserialize<'de>> Deserialize<'de> for AssignmentTarget<E> {
216 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
217 #[derive(Deserialize)]
218 #[serde(untagged)]
219 enum Target<E> {
220 Column(String),
221 Partial {
222 column: String,
223 indirection: Vec<AssignmentStep<E>>,
224 },
225 }
226 Ok(match Target::deserialize(deserializer)? {
227 Target::Column(column) => column.into(),
228 Target::Partial {
229 column,
230 indirection,
231 } => Self {
232 column,
233 indirection,
234 },
235 })
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[test]
244 fn ordinary_target_encoding_preserves_predecessor_definitions() {
245 let target: AssignmentTarget<i32> = serde_json::from_str("\"value\"").unwrap();
246 assert!(target.is_whole_column());
247 assert_eq!(target.column, "value");
248 assert_eq!(serde_json::to_string(&target).unwrap(), "\"value\"");
249 let group: AssignmentTargets<i32> = serde_json::from_str("\"value\"").unwrap();
250 assert!(matches!(group, AssignmentTargets::Single(_)));
251 assert_eq!(serde_json::to_string(&group).unwrap(), "\"value\"");
252 let grouped: AssignmentTargets<i32> =
253 AssignmentTargets::Multiple(vec!["a".into(), "b".into()].into());
254 let encoded = serde_json::to_string(&grouped).unwrap();
255 assert_eq!(
256 serde_json::from_str::<AssignmentTargets<i32>>(&encoded).unwrap(),
257 grouped
258 );
259 }
260
261 #[test]
262 fn partial_targets_keep_bound_omission_order_and_expression_rewrites() {
263 let mut target = AssignmentTarget {
264 column: "value".into(),
265 indirection: vec![
266 AssignmentStep::Index(Box::new(1)),
267 AssignmentStep::Field("items".into()),
268 AssignmentStep::Slice {
269 lower: None,
270 upper: Some(Box::new(2)),
271 },
272 AssignmentStep::Slice {
273 lower: Some(Box::new(3)),
274 upper: None,
275 },
276 ],
277 };
278 for value in target.expressions_mut() {
279 *value += 10;
280 }
281 assert_eq!(
282 target.expressions().copied().collect::<Vec<_>>(),
283 [11, 12, 13]
284 );
285 let rendered = serde_json::to_string(&target).unwrap();
286 assert_eq!(
287 serde_json::from_str::<AssignmentTarget<i32>>(&rendered).unwrap(),
288 target
289 );
290 let lowered = target.map(|value| value.to_string());
291 assert_eq!(
292 lowered
293 .expressions()
294 .map(String::as_str)
295 .collect::<Vec<_>>(),
296 ["11", "12", "13"]
297 );
298 assert!(matches!(
299 lowered.indirection[2],
300 AssignmentStep::Slice { lower: None, .. }
301 ));
302 assert!(matches!(
303 lowered.indirection[3],
304 AssignmentStep::Slice { upper: None, .. }
305 ));
306 }
307}