1use crate::element::builders::StructBuilder;
2use crate::element::Element;
3use crate::ion_data::{IonDataHash, IonDataOrd, IonEq};
4use crate::symbol_ref::AsSymbolRef;
5use crate::text::text_formatter::FmtValueFormatter;
6use crate::Symbol;
7use smallvec::SmallVec;
8use std::cmp::Ordering;
9use std::collections::{HashMap, VecDeque};
10use std::fmt::{Display, Formatter};
11use std::hash::Hasher;
12
13type IndexVec = SmallVec<[usize; 1]>;
16
17#[derive(Debug, Clone)]
19struct Fields {
20 by_index: Vec<(Symbol, Element)>,
22 by_name: HashMap<Symbol, IndexVec>,
24}
25
26impl Fields {
27 fn get_indexes<A: AsSymbolRef>(&self, field_name: A) -> Option<&IndexVec> {
29 field_name
30 .as_symbol_ref()
31 .text()
32 .map(|text| {
33 self.by_name.get(text)
35 })
36 .unwrap_or_else(|| {
37 let symbol = Symbol::unknown_text();
39 self.by_name.get(&symbol)
41 })
42 }
43
44 fn get_values_at_indexes<'a>(&'a self, indexes: &'a IndexVec) -> FieldValuesIterator<'a> {
46 FieldValuesIterator {
47 current: 0,
48 indexes: Some(indexes),
49 by_index: &self.by_index,
50 }
51 }
52
53 fn get_last<A: AsSymbolRef>(&self, field_name: A) -> Option<&Element> {
62 self.get_indexes(field_name)
63 .and_then(|indexes| indexes.last())
64 .and_then(|index| self.by_index.get(*index))
65 .map(|(_name, value)| value)
66 }
67
68 fn get_all<A: AsSymbolRef>(&self, field_name: A) -> FieldValuesIterator<'_> {
70 let indexes = self.get_indexes(field_name);
71 FieldValuesIterator {
72 current: 0,
73 indexes,
74 by_index: &self.by_index,
75 }
76 }
77
78 fn iter(&self) -> impl Iterator<Item = &(Symbol, Element)> {
80 self.by_index.iter()
81 }
82}
83
84pub struct FieldIterator<'a> {
86 values: Option<std::slice::Iter<'a, (Symbol, Element)>>,
87}
88
89impl<'a> FieldIterator<'a> {
90 fn new(data: &'a [(Symbol, Element)]) -> Self {
91 FieldIterator {
92 values: Some(data.iter()),
93 }
94 }
95}
96
97impl<'a> Iterator for FieldIterator<'a> {
98 type Item = (&'a Symbol, &'a Element);
99
100 fn next(&mut self) -> Option<Self::Item> {
101 self.values
102 .as_mut()
103 .and_then(|iter| iter.next().map(|field| (&field.0, &field.1)))
105 }
106}
107
108pub struct OwnedFieldIterator {
110 fields: VecDeque<(Symbol, Element)>,
111}
112
113impl OwnedFieldIterator {
114 fn new(data: Vec<(Symbol, Element)>) -> Self {
115 OwnedFieldIterator {
116 fields: data.into(),
117 }
118 }
119}
120
121impl Iterator for OwnedFieldIterator {
122 type Item = (Symbol, Element);
123
124 fn next(&mut self) -> Option<Self::Item> {
125 self.fields.pop_front()
126 }
127
128 fn size_hint(&self) -> (usize, Option<usize>) {
129 let len = self.fields.len();
130 (len, Some(len))
131 }
132}
133
134pub(crate) struct FieldValuesIterator<'a> {
136 current: usize,
137 indexes: Option<&'a IndexVec>,
138 by_index: &'a Vec<(Symbol, Element)>,
139}
140
141impl<'a> Iterator for FieldValuesIterator<'a> {
142 type Item = &'a Element;
143
144 fn next(&mut self) -> Option<Self::Item> {
145 self.indexes
146 .and_then(|i| i.get(self.current))
147 .and_then(|i| {
148 self.current += 1;
149 self.by_index.get(*i)
150 })
151 .map(|(_name, value)| value)
152 }
153}
154
155#[derive(Debug, Clone)]
171pub struct Struct {
172 fields: Fields,
173}
174
175impl Display for Struct {
176 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
177 let mut ivf = FmtValueFormatter { output: f };
178 ivf.format_struct(self).map_err(|_| std::fmt::Error)?;
179 Ok(())
180 }
181}
182
183impl Struct {
184 pub fn builder() -> StructBuilder {
185 StructBuilder::new()
186 }
187
188 pub fn clone_builder(&self) -> StructBuilder {
189 StructBuilder::with_initial_fields(&self.fields.by_index)
190 }
191
192 #[allow(clippy::map_identity)]
194 pub fn fields(&self) -> impl Iterator<Item = (&Symbol, &Element)> {
197 self.fields
198 .iter()
199 .map(|(name, element)| (name, element))
203 }
204
205 fn fields_eq(&self, other: &Self, eq: impl Fn(&Element, &Element) -> bool) -> bool {
206 if self.fields.by_index.len() != self.fields.by_name.len() {
207 return self.fields_with_repeated_names_eq(other, eq);
208 }
209
210 for (field_name, field_value_indexes) in &self.fields.by_name {
211 let other_value_indexes = match other.fields.get_indexes(field_name) {
212 Some(indexes) => indexes,
213 None => return false,
215 };
216
217 debug_assert_eq!(field_value_indexes.len(), 1);
218 if other_value_indexes.len() != 1 {
219 return false;
221 }
222
223 let self_value = &self.fields.by_index[field_value_indexes[0]].1;
225 let other_value = &other.fields.by_index[other_value_indexes[0]].1;
226 if !eq(self_value, other_value) {
227 return false;
228 }
229 }
230
231 true
232 }
233
234 fn fields_with_repeated_names_eq(
237 &self,
238 other: &Self,
239 eq: impl Fn(&Element, &Element) -> bool,
240 ) -> bool {
241 for (field_name, field_value_indexes) in &self.fields.by_name {
242 let other_value_indexes = match other.fields.get_indexes(field_name) {
243 Some(indexes) => indexes,
244 None => return false,
245 };
246
247 if field_value_indexes.len() != other_value_indexes.len() {
248 return false;
249 }
250
251 let mut matched = vec![false; other_value_indexes.len()];
252 for field_value in self.fields.get_values_at_indexes(field_value_indexes) {
253 let found = other
254 .fields
255 .get_values_at_indexes(other_value_indexes)
256 .enumerate()
257 .find(|(i, other_value)| !matched[*i] && eq(field_value, other_value));
258 match found {
259 Some((i, _)) => matched[i] = true,
260 None => return false,
261 }
262 }
263 }
264
265 true
266 }
267
268 pub fn len(&self) -> usize {
270 self.fields.by_index.len()
271 }
272
273 pub fn is_empty(&self) -> bool {
275 self.len() == 0
276 }
277
278 pub fn iter(&self) -> FieldIterator<'_> {
279 FieldIterator::new(&self.fields.by_index)
280 }
281
282 pub fn get<A: AsSymbolRef>(&self, field_name: A) -> Option<&Element> {
288 self.fields.get_last(field_name)
289 }
290
291 pub fn get_all<A: AsSymbolRef>(&self, field_name: A) -> impl Iterator<Item = &Element> {
293 self.fields.get_all(field_name)
294 }
295}
296
297impl<'a> IntoIterator for &'a Struct {
299 type Item = (&'a Symbol, &'a Element);
300 type IntoIter = FieldIterator<'a>;
301
302 fn into_iter(self) -> Self::IntoIter {
303 self.iter()
304 }
305}
306
307impl IntoIterator for Struct {
309 type Item = (Symbol, Element);
310 type IntoIter = OwnedFieldIterator;
311
312 fn into_iter(self) -> Self::IntoIter {
313 OwnedFieldIterator::new(self.fields.by_index)
314 }
315}
316
317impl<K, V> FromIterator<(K, V)> for Struct
318where
319 K: Into<Symbol>,
320 V: Into<Element>,
321{
322 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
324 let mut by_index: Vec<(Symbol, Element)> = Vec::new();
325 let mut by_name: HashMap<Symbol, IndexVec> = HashMap::new();
326 for (field_name, field_value) in iter {
327 let field_name = field_name.into();
328 let field_value = field_value.into();
329
330 by_name
331 .entry(field_name.clone())
332 .or_default()
333 .push(by_index.len());
334 by_index.push((field_name, field_value));
335 }
336
337 let fields = Fields { by_index, by_name };
338 Self { fields }
339 }
340}
341
342impl PartialEq for Struct {
343 fn eq(&self, other: &Self) -> bool {
344 self.len() == other.len() && self.fields_eq(other, |a, b| a == b)
345 }
346}
347
348impl IonEq for Struct {
349 fn ion_eq(&self, other: &Self) -> bool {
350 self.len() == other.len() && self.fields_eq(other, |a, b| a.ion_eq(b))
351 }
352}
353
354impl IonDataOrd for Struct {
355 fn ion_cmp(&self, other: &Self) -> Ordering {
356 let mut these_fields = self.fields.by_index.iter().collect::<Vec<_>>();
357 let mut those_fields = other.fields.by_index.iter().collect::<Vec<_>>();
358 these_fields.sort_by(ion_cmp_field);
359 those_fields.sort_by(ion_cmp_field);
360
361 let mut i0 = these_fields.iter();
362 let mut i1 = those_fields.iter();
363 loop {
364 match [i0.next(), i1.next()] {
365 [None, Some(_)] => return Ordering::Less,
366 [None, None] => return Ordering::Equal,
367 [Some(_), None] => return Ordering::Greater,
368 [Some(a), Some(b)] => {
369 let ord = ion_cmp_field(a, b);
370 if ord != Ordering::Equal {
371 return ord;
372 }
373 }
374 }
375 }
376 }
377}
378
379fn ion_cmp_field(this: &&(Symbol, Element), that: &&(Symbol, Element)) -> Ordering {
380 let ord = this.0.ion_cmp(&that.0);
381 if !ord.is_eq() {
382 return ord;
383 }
384 IonDataOrd::ion_cmp(&this.1, &that.1)
385}
386
387impl IonDataHash for Struct {
388 fn ion_data_hash<H: Hasher>(&self, state: &mut H) {
389 let mut these_fields = self.fields.by_index.iter().collect::<Vec<_>>();
390 these_fields.sort_by(ion_cmp_field);
391 for (name, value) in these_fields {
392 name.ion_data_hash(state);
393 value.ion_data_hash(state);
394 }
395 }
396}
397
398#[cfg(test)]
399mod tests {
400 use crate::element::Element;
401 use crate::ion_data::IonEq;
402 use crate::ion_struct;
403
404 #[test]
405 fn duplicate_field_values_not_equal() {
406 let s1 = ion_struct! { "a": 1, "a": 1, "a": 2 };
407 let s2 = ion_struct! { "a": 1, "a": 2, "a": 2 };
408 assert_ne!(s1, s2);
409 assert!(!s1.ion_eq(&s2));
410 }
411
412 #[test]
413 fn same_multiset_different_order_is_equal() {
414 let s1 = ion_struct! { "a": 1, "a": 2, "b": 3 };
415 let s2 = ion_struct! { "b": 3, "a": 2, "a": 1 };
416 assert_eq!(s1, s2);
417 assert!(s1.ion_eq(&s2));
418 }
419
420 #[test]
421 fn nan_partial_eq_vs_ion_eq() {
422 let s1 = ion_struct! { "x": f64::NAN };
423 let s2 = ion_struct! { "x": f64::NAN };
424 assert_ne!(s1, s2);
426 assert!(s1.ion_eq(&s2));
428 }
429
430 #[test]
431 fn signed_zero_partial_eq_vs_ion_eq() {
432 let s1 = ion_struct! { "x": 0.0f64 };
433 let s2 = ion_struct! { "x": -0.0f64 };
434 assert_eq!(s1, s2);
436 assert!(!s1.ion_eq(&s2));
438 }
439
440 #[test]
441 fn for_field_in_struct() {
442 let s = ion_struct! { "foo": 1, "bar": 2, "baz": 3};
444 let _fields = s.clone().iter().collect::<Vec<_>>(); let mut baz_value = None;
446 for (name, value) in &s {
447 if *name == "baz" {
448 baz_value = Some(value);
449 }
450 }
451 assert_eq!(baz_value, Some(&Element::int(3)));
452 }
453
454 #[test]
455 fn for_field_in_owned_struct() {
456 let s = ion_struct! { "foo": 1, "bar": 2, "baz": 3};
458 let _fields = s.clone().into_iter().collect::<Vec<_>>(); let mut baz_value = None;
460 for (name, value) in s {
461 if name == "baz" {
462 baz_value = Some(value);
463 }
464 }
465 assert_eq!(baz_value, Some(Element::int(3)));
466 }
467}