vdf_reader/entry/
table.rs

1use super::{Array, Entry};
2use crate::entry::{string_is_array, Statement, Value};
3use crate::error::UnknownError;
4use crate::event::{EntryEvent, GroupStartEvent, ValueContinuationEvent};
5use crate::{Event, Item, Reader, Result, VdfError};
6use serde_core::de::{DeserializeSeed, MapAccess};
7use serde_core::{Deserialize, Deserializer, Serialize, Serializer};
8use std::collections::hash_map;
9use std::collections::HashMap;
10use std::ops::{Deref, DerefMut};
11
12/// A table of entries.
13#[derive(Clone, PartialEq, Eq, Debug, Default)]
14pub struct Table(HashMap<String, Entry>); // todo: switch to a map that maintains item order
15
16impl<'de> Deserialize<'de> for Table {
17    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
18    where
19        D: Deserializer<'de>,
20    {
21        HashMap::deserialize(deserializer).map(Table)
22    }
23}
24
25impl Serialize for Table {
26    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
27    where
28        S: Serializer,
29    {
30        use std::collections::BTreeMap;
31        let ordered: BTreeMap<_, _> = self.0.iter().collect();
32        ordered.serialize(serializer)
33    }
34}
35
36impl From<HashMap<String, Entry>> for Table {
37    fn from(value: HashMap<String, Entry>) -> Self {
38        Table(value)
39    }
40}
41
42fn insert<K: Into<String>, V: Into<Entry>>(map: &mut HashMap<String, Entry>, key: K, value: V) {
43    let key = key.into();
44    let value = value.into();
45    let entry = map.entry(key);
46    match entry {
47        hash_map::Entry::Vacant(entry) => {
48            entry.insert(value);
49        }
50        hash_map::Entry::Occupied(mut entry) => match entry.get_mut() {
51            Entry::Array(ref mut array) => {
52                array.push(value);
53            }
54            _ => {
55                let (key, old_value) = entry.remove_entry();
56                let mut array = Array::from(old_value);
57                array.push(value);
58                map.insert(key, Entry::Array(array));
59            }
60        },
61    }
62}
63
64impl Table {
65    pub fn load_from_str(input: &str) -> Result<Table> {
66        let mut reader = Reader::from(input);
67        Self::load(&mut reader)
68    }
69
70    /// Load a table from the given `Reader`.
71    pub fn load(reader: &mut Reader) -> Result<Table> {
72        let mut map = HashMap::new();
73        let mut last_key = None;
74
75        while let Some(event) = reader.event() {
76            last_key = match event? {
77                Event::Entry(EntryEvent {
78                    key: Item::Item { content: key, .. },
79                    value,
80                    ..
81                }) => {
82                    let str = value.as_str();
83                    let key_clone = key.clone();
84                    if string_is_array(str) {
85                        insert(
86                            &mut map,
87                            key,
88                            Array::from_space_separated(str[1..str.len() - 1].trim()),
89                        )
90                    } else {
91                        insert(&mut map, key, Value::from(value.into_content()))
92                    }
93                    Some(key_clone)
94                }
95
96                Event::Entry(EntryEvent {
97                    key: Item::Statement { content: key, .. },
98                    value,
99                    ..
100                }) => {
101                    let key_clone = key.clone();
102                    insert(&mut map, key, Statement::from(value.into_content()));
103                    Some(key_clone)
104                }
105
106                Event::ValueContinuation(ValueContinuationEvent { value, .. }) => {
107                    if let Some(key) = last_key.as_ref() {
108                        if let Some(last_value) = map.get_mut(key.as_ref()) {
109                            last_value.push(Value::from(value.into_content()).into())?;
110                        }
111                    }
112                    last_key
113                }
114
115                Event::GroupStart(GroupStartEvent { name, .. }) => {
116                    insert(&mut map, name, Table::load(reader)?);
117                    None
118                }
119
120                Event::GroupEnd(_) => break,
121            }
122        }
123
124        Ok(Table(map))
125    }
126}
127
128impl IntoIterator for Table {
129    type Item = (String, Entry);
130    type IntoIter = hash_map::IntoIter<String, Entry>;
131
132    fn into_iter(self) -> Self::IntoIter {
133        self.0.into_iter()
134    }
135}
136
137impl From<Table> for Entry {
138    fn from(table: Table) -> Self {
139        Entry::Table(table)
140    }
141}
142
143impl From<Table> for HashMap<String, Entry> {
144    fn from(table: Table) -> Self {
145        table.0
146    }
147}
148
149impl Deref for Table {
150    type Target = HashMap<String, Entry>;
151
152    fn deref(&self) -> &Self::Target {
153        &self.0
154    }
155}
156
157impl DerefMut for Table {
158    fn deref_mut(&mut self) -> &mut Self::Target {
159        &mut self.0
160    }
161}
162
163pub(crate) struct TableSeq {
164    iter: hash_map::IntoIter<String, Entry>,
165    next_item: Option<Entry>,
166}
167
168impl TableSeq {
169    pub(crate) fn new(table: Table) -> Self {
170        TableSeq {
171            iter: table.0.into_iter(),
172            next_item: None,
173        }
174    }
175}
176
177impl<'de> MapAccess<'de> for TableSeq {
178    type Error = VdfError;
179
180    fn next_key_seed<K>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, Self::Error>
181    where
182        K: DeserializeSeed<'de>,
183    {
184        let (key, value) = match self.iter.next() {
185            Some(pair) => pair,
186            None => {
187                return Ok(None);
188            }
189        };
190        self.next_item = Some(value);
191        seed.deserialize(Value::from(key)).map(Some)
192    }
193
194    fn next_value_seed<V>(&mut self, seed: V) -> std::result::Result<V::Value, Self::Error>
195    where
196        V: DeserializeSeed<'de>,
197    {
198        let item = match self.next_item.take() {
199            Some(item) => item,
200            None => return Err(UnknownError::from("double take value").into()),
201        };
202
203        seed.deserialize(item)
204    }
205}
206
207#[cfg(test)]
208#[track_caller]
209fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
210    r.map_err(miette::Error::from).unwrap()
211}
212
213#[test]
214fn test_serde_table() {
215    use maplit::hashmap;
216
217    let j = r#"{foo bar}"#;
218
219    assert_eq!(
220        Table(hashmap! {"foo".into() => Entry::Value("bar".into())}),
221        unwrap_err(crate::from_str(j))
222    );
223}