Skip to main content

substrate_data/model/map/
map.rs

1//! [`Map`]: entries in file order, indexed once it's big.
2
3use std::collections::HashMap;
4use std::sync::OnceLock;
5
6use crate::model::value::Value;
7use crate::sync::Arc;
8
9/// How many keys a map has before a lookup indexes them: below it a scan
10/// beats hashing (`benches/data.rs`'s maps, small records).
11pub(super) const INDEXED_FROM: usize = 32;
12
13/// Keys are shared: a decoded document allocates each distinct key once,
14/// however many maps have it.
15#[derive(Clone, Default)]
16pub struct Map {
17    entries: Vec<(Arc<str>, Value)>,
18    /// Each key's position, once a lookup in a big map asked for it;
19    /// boxed, so a map (and so every [`Value`]) is no bigger for it.
20    index: OnceLock<Box<KeyIndex>>,
21}
22
23/// Each key's position among a map's entries.
24#[derive(Clone, Default)]
25struct KeyIndex(HashMap<Arc<str>, usize>);
26
27impl std::fmt::Debug for Map {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        f.debug_tuple("Map").field(&self.entries).finish()
30    }
31}
32
33impl PartialEq for Map {
34    fn eq(&self, other: &Self) -> bool {
35        self.entries == other.entries
36    }
37}
38
39impl Map {
40    /// An empty map.
41    #[must_use]
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    /// An empty map with room for `n` entries.
47    #[must_use]
48    pub fn with_capacity(n: usize) -> Self {
49        Self {
50            entries: Vec::with_capacity(n),
51            index: OnceLock::new(),
52        }
53    }
54
55    /// Where `key` is: by the index in a big map (made now if it isn't
56    /// yet), by a scan in a small one.
57    fn position(&self, key: &str) -> Option<usize> {
58        if self.entries.len() < INDEXED_FROM {
59            return self.entries.iter().position(|(k, _)| &**k == key);
60        }
61        let index = self.index.get_or_init(|| {
62            Box::new(KeyIndex(
63                self.entries
64                    .iter()
65                    .enumerate()
66                    .map(|(i, (k, _))| (k.clone(), i))
67                    .collect(),
68            ))
69        });
70        index.0.get(key).copied()
71    }
72
73    /// The index, if one's made: what a change keeps current.
74    fn index_mut(&mut self) -> Option<&mut HashMap<Arc<str>, usize>> {
75        self.index.get_mut().map(|b| &mut b.0)
76    }
77
78    /// The value of `key`.
79    pub fn get(&self, key: &str) -> Option<&Value> {
80        self.position(key).map(|i| &self.entries[i].1)
81    }
82
83    /// The value of `key`, to change.
84    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
85        let i = self.position(key)?;
86        Some(&mut self.entries[i].1)
87    }
88
89    /// The value of the `i`-th entry.
90    pub fn value_at(&self, i: usize) -> Option<&Value> {
91        self.entries.get(i).map(|(_, v)| v)
92    }
93
94    /// The position of `key` among the entries.
95    pub fn index_of(&self, key: &str) -> Option<usize> {
96        self.position(key)
97    }
98
99    /// Sets `key`, in place if it's there, else at the end; returns the old value.
100    pub fn insert(&mut self, key: impl Into<String>, value: Value) -> Option<Value> {
101        let key = key.into();
102        if let Some(slot) = self.get_mut(&key) {
103            return Some(std::mem::replace(slot, value));
104        }
105        self.push_unchecked(key.into(), value);
106        None
107    }
108
109    /// Appends without checking for the key — for decoders that already did.
110    pub(crate) fn push_unchecked(&mut self, key: Arc<str>, value: Value) {
111        let at = self.entries.len();
112        if let Some(index) = self.index_mut() {
113            index.insert(key.clone(), at);
114        }
115        self.entries.push((key, value));
116    }
117
118    /// Takes `key`'s entry out: its value, the others keeping their order.
119    pub fn remove(&mut self, key: &str) -> Option<Value> {
120        let i = self.position(key)?;
121        let (_, value) = self.entries.remove(i);
122        if let Some(index) = self.index_mut() {
123            index.remove(key);
124            for at in index.values_mut() {
125                if *at > i {
126                    *at -= 1;
127                }
128            }
129        }
130        Some(value)
131    }
132
133    /// How many entries.
134    pub fn len(&self) -> usize {
135        self.entries.len()
136    }
137
138    /// Whether it has no entries.
139    pub fn is_empty(&self) -> bool {
140        self.entries.is_empty()
141    }
142
143    /// The entries, in order.
144    pub fn iter(&self) -> impl ExactSizeIterator<Item = (&str, &Value)> {
145        self.entries.iter().map(|(k, v)| (&**k, v))
146    }
147
148    /// The keys, in order.
149    pub fn keys(&self) -> impl ExactSizeIterator<Item = &str> {
150        self.entries.iter().map(|(k, _)| &**k)
151    }
152
153    /// The values, in order.
154    pub fn values(&self) -> impl ExactSizeIterator<Item = &Value> {
155        self.entries.iter().map(|(_, v)| v)
156    }
157
158    /// Keeps the entries `keep` says to, in one pass; the index made again
159    /// when it's next needed.
160    pub fn retain(&mut self, mut keep: impl FnMut(&str, &Value) -> bool) {
161        self.entries.retain(|(k, v)| keep(k, v));
162        self.index = OnceLock::new();
163    }
164}
165
166impl IntoIterator for Map {
167    type Item = (String, Value);
168    type IntoIter = std::iter::Map<
169        std::vec::IntoIter<(Arc<str>, Value)>,
170        fn((Arc<str>, Value)) -> (String, Value),
171    >;
172    fn into_iter(self) -> Self::IntoIter {
173        self.entries.into_iter().map(|(k, v)| (k.to_string(), v))
174    }
175}
176
177impl<'a> IntoIterator for &'a Map {
178    type Item = (&'a str, &'a Value);
179    type IntoIter = std::iter::Map<
180        std::slice::Iter<'a, (Arc<str>, Value)>,
181        fn(&'a (Arc<str>, Value)) -> (&'a str, &'a Value),
182    >;
183    fn into_iter(self) -> Self::IntoIter {
184        self.entries.iter().map(|(k, v)| (&**k, v))
185    }
186}
187
188impl<K: Into<String>> FromIterator<(K, Value)> for Map {
189    fn from_iter<I: IntoIterator<Item = (K, Value)>>(iter: I) -> Self {
190        let mut map = Map::new();
191        for (k, v) in iter {
192            map.insert(k, v);
193        }
194        map
195    }
196}