substrate_data/schema/plain/
maps.rs1use std::collections::{BTreeMap, HashMap};
4use std::hash::BuildHasher;
5
6use crate::model::borrowed::ValueRef;
7use crate::model::value::{Seg, Value};
8use crate::schema::{Reader, Schema, Shape, is_metadata_key};
9
10pub(super) fn read_map<T: Schema>(
12 v: &ValueRef<'_>,
13 cx: &mut Reader<'_>,
14 mut put: impl FnMut(String, T),
15) -> Option<()> {
16 let map = cx.map(v)?;
17 let mut ok = true;
18 for (k, item) in map.iter() {
19 if is_metadata_key(k) {
20 continue;
21 }
22 match cx.at(Seg::Key(k.to_string()), |cx| T::read(item, cx)) {
23 Some(x) => put(k.to_string(), x),
24 None => ok = false,
25 }
26 }
27 ok.then_some(())
28}
29
30impl<T: Schema> Schema for BTreeMap<String, T> {
31 fn shape() -> Shape {
32 Shape::Map(T::shape)
33 }
34 fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
35 let mut out = BTreeMap::new();
36 read_map(v, cx, |k, x| {
37 out.insert(k, x);
38 })?;
39 Some(out)
40 }
41 fn write(&self) -> Value {
42 Value::Map(self.iter().map(|(k, v)| (k.clone(), v.write())).collect())
43 }
44}
45
46impl<T: Schema, S: BuildHasher + Default> Schema for HashMap<String, T, S> {
47 fn shape() -> Shape {
48 Shape::Map(T::shape)
49 }
50 fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
51 let mut out = HashMap::default();
52 read_map(v, cx, |k, x| {
53 out.insert(k, x);
54 })?;
55 Some(out)
56 }
57 fn write(&self) -> Value {
58 let mut keys: Vec<&String> = self.keys().collect();
59 keys.sort();
60 Value::Map(
61 keys.into_iter()
62 .map(|k| (k.clone(), self[k].write()))
63 .collect(),
64 )
65 }
66}