1use crate::element::builders::StructBuilder;
2use crate::element::Element;
3use crate::ion_data::{IonEq, IonOrd};
4use crate::symbol_ref::AsSymbolRef;
5use crate::text::text_formatter::IonValueFormatter;
6use crate::Symbol;
7use smallvec::SmallVec;
8use std::cmp::Ordering;
9use std::collections::HashMap;
10use std::fmt::{Display, Formatter};
11
12type IndexVec = SmallVec<[usize; 1]>;
15
16#[derive(Debug, Clone)]
18struct Fields {
19 by_index: Vec<(Symbol, Element)>,
21 by_name: HashMap<Symbol, IndexVec>,
23}
24
25impl Fields {
26 fn get_indexes<A: AsSymbolRef>(&self, field_name: A) -> Option<&IndexVec> {
28 field_name
29 .as_symbol_ref()
30 .text()
31 .map(|text| {
32 self.by_name.get(text)
34 })
35 .unwrap_or_else(|| {
36 let symbol = Symbol::unknown_text();
38 self.by_name.get(&symbol)
40 })
41 }
42
43 fn get_values_at_indexes<'a>(&'a self, indexes: &'a IndexVec) -> FieldValuesIterator<'a> {
45 FieldValuesIterator {
46 current: 0,
47 indexes: Some(indexes),
48 by_index: &self.by_index,
49 }
50 }
51
52 fn get_last<A: AsSymbolRef>(&self, field_name: A) -> Option<&Element> {
61 self.get_indexes(field_name)
62 .and_then(|indexes| indexes.last())
63 .and_then(|index| self.by_index.get(*index))
64 .map(|(_name, value)| value)
65 }
66
67 fn get_all<A: AsSymbolRef>(&self, field_name: A) -> FieldValuesIterator {
69 let indexes = self.get_indexes(field_name);
70 FieldValuesIterator {
71 current: 0,
72 indexes,
73 by_index: &self.by_index,
74 }
75 }
76
77 fn iter(&self) -> impl Iterator<Item = &(Symbol, Element)> {
79 self.by_index.iter()
80 }
81}
82
83pub struct FieldIterator<'a> {
85 values: Option<std::slice::Iter<'a, (Symbol, Element)>>,
86}
87
88impl<'a> FieldIterator<'a> {
89 fn new(data: &'a [(Symbol, Element)]) -> Self {
90 FieldIterator {
91 values: Some(data.iter()),
92 }
93 }
94
95 fn empty() -> FieldIterator<'static> {
96 FieldIterator { values: None }
97 }
98}
99
100impl<'a> Iterator for FieldIterator<'a> {
101 type Item = (&'a Symbol, &'a Element);
102
103 fn next(&mut self) -> Option<Self::Item> {
104 self.values
105 .as_mut()
106 .and_then(|iter| iter.next().map(|field| (&field.0, &field.1)))
108 }
109}
110
111pub struct FieldValuesIterator<'a> {
113 current: usize,
114 indexes: Option<&'a IndexVec>,
115 by_index: &'a Vec<(Symbol, Element)>,
116}
117
118impl<'a> Iterator for FieldValuesIterator<'a> {
119 type Item = &'a Element;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 self.indexes
123 .and_then(|i| i.get(self.current))
124 .and_then(|i| {
125 self.current += 1;
126 self.by_index.get(*i)
127 })
128 .map(|(_name, value)| value)
129 }
130}
131
132#[derive(Debug, Clone)]
149pub struct Struct {
150 fields: Fields,
151}
152
153impl Display for Struct {
154 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
155 let mut ivf = IonValueFormatter { output: f };
156 ivf.format_struct(self).map_err(|_| std::fmt::Error)?;
157 Ok(())
158 }
159}
160
161impl Struct {
162 pub fn builder() -> StructBuilder {
163 StructBuilder::new()
164 }
165
166 pub fn clone_builder(&self) -> StructBuilder {
167 StructBuilder::with_initial_fields(&self.fields.by_index)
168 }
169
170 pub fn fields(&self) -> impl Iterator<Item = (&Symbol, &Element)> {
172 self.fields
173 .iter()
174 .map(|(name, element)| (name, element))
178 }
179
180 fn fields_eq(&self, other: &Self) -> bool {
181 for (field_name, field_value_indexes) in &self.fields.by_name {
183 let other_value_indexes = match other.fields.get_indexes(field_name) {
184 Some(indexes) => indexes,
185 None => return false,
187 };
188
189 if field_value_indexes.len() != other_value_indexes.len() {
190 return false;
192 }
193
194 for field_value in self.fields.get_values_at_indexes(field_value_indexes) {
195 if other
196 .fields
197 .get_values_at_indexes(other_value_indexes)
198 .all(|other_value| !field_value.ion_eq(other_value))
199 {
200 return false;
202 }
203 }
204 }
205
206 true
208 }
209
210 pub fn len(&self) -> usize {
212 self.fields.by_index.len()
213 }
214
215 pub fn is_empty(&self) -> bool {
217 self.len() == 0
218 }
219
220 pub fn iter(&self) -> FieldIterator<'_> {
221 FieldIterator::new(&self.fields.by_index)
222 }
223
224 pub fn get<A: AsSymbolRef>(&self, field_name: A) -> Option<&Element> {
225 self.fields.get_last(field_name)
226 }
227
228 pub fn get_all<A: AsSymbolRef>(&self, field_name: A) -> FieldValuesIterator<'_> {
229 self.fields.get_all(field_name)
230 }
231}
232
233impl<'a> IntoIterator for &'a Struct {
235 type Item = (&'a Symbol, &'a Element);
236 type IntoIter = FieldIterator<'a>;
237
238 fn into_iter(self) -> Self::IntoIter {
239 self.iter()
240 }
241}
242
243impl<K, V> FromIterator<(K, V)> for Struct
244where
245 K: Into<Symbol>,
246 V: Into<Element>,
247{
248 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
250 let mut by_index: Vec<(Symbol, Element)> = Vec::new();
251 let mut by_name: HashMap<Symbol, IndexVec> = HashMap::new();
252 for (field_name, field_value) in iter {
253 let field_name = field_name.into();
254 let field_value = field_value.into();
255
256 by_name
257 .entry(field_name.clone())
258 .or_insert_with(IndexVec::new)
259 .push(by_index.len());
260 by_index.push((field_name, field_value));
261 }
262
263 let fields = Fields { by_index, by_name };
264 Self { fields }
265 }
266}
267
268impl PartialEq for Struct {
269 fn eq(&self, other: &Self) -> bool {
270 self.len() == other.len()
272 && self.fields_eq(other) && other.fields_eq(self)
277 }
278}
279
280impl Eq for Struct {}
281
282impl IonEq for Struct {
283 fn ion_eq(&self, other: &Self) -> bool {
284 self == other
285 }
286}
287
288impl IonOrd for Struct {
289 fn ion_cmp(&self, other: &Self) -> Ordering {
290 let mut these_fields = self.fields.by_index.iter().collect::<Vec<_>>();
291 let mut those_fields = other.fields.by_index.iter().collect::<Vec<_>>();
292 these_fields.sort_by(ion_cmp_field);
293 those_fields.sort_by(ion_cmp_field);
294
295 let mut i0 = these_fields.iter();
296 let mut i1 = those_fields.iter();
297 loop {
298 match [i0.next(), i1.next()] {
299 [None, Some(_)] => return Ordering::Less,
300 [None, None] => return Ordering::Equal,
301 [Some(_), None] => return Ordering::Greater,
302 [Some(a), Some(b)] => {
303 let ord = ion_cmp_field(a, b);
304 if ord != Ordering::Equal {
305 return ord;
306 }
307 }
308 }
309 }
310 }
311}
312
313fn ion_cmp_field(this: &&(Symbol, Element), that: &&(Symbol, Element)) -> Ordering {
314 let ord = this.0.ion_cmp(&that.0);
315 if !ord.is_eq() {
316 return ord;
317 }
318 IonOrd::ion_cmp(&this.1, &that.1)
319}
320
321#[cfg(test)]
322mod tests {
323 use crate::element::Element;
324 use crate::ion_struct;
325
326 #[test]
327 fn for_field_in_struct() {
328 let s = ion_struct! { "foo": 1, "bar": 2, "baz": 3};
330 let mut baz_value = None;
331 for (name, value) in &s {
332 if *name == "baz" {
333 baz_value = Some(value);
334 }
335 }
336 assert_eq!(baz_value, Some(&Element::integer(3)));
337 }
338}