Skip to main content

substrate_data/wire/binary/
decoder_ref.rs

1//! [`Decoder`] reading a value borrowed: strings point into the bytes,
2//! lists and maps go in an arena.
3
4use bumpalo::Bump;
5
6use super::decoder::{F32_BYTES, F64_BYTES, MAP_ENTRY_MIN};
7use super::seen_keys::SeenKeys;
8use super::{DecodeError, Decoder, tag, unzigzag};
9use crate::model::borrowed::{MapRef, ValueRef};
10
11impl<'b> Decoder<'b> {
12    /// The next value, borrowed: strings point into the bytes, lists and maps go in `arena`.
13    ///
14    /// # Errors
15    ///
16    /// [`DecodeError`] when the bytes aren't a value.
17    pub fn value_ref<'a>(&mut self, arena: &'a Bump) -> Result<ValueRef<'a>, DecodeError>
18    where
19        'b: 'a,
20    {
21        let mut stack = Vec::new();
22        self.value_ref_in(arena, &mut stack)
23    }
24
25    /// [`Decoder::value_ref`]: children gather on `stack`, then move into `arena` as one slice.
26    fn value_ref_in<'a>(
27        &mut self,
28        arena: &'a Bump,
29        stack: &mut Vec<ValueRef<'a>>,
30    ) -> Result<ValueRef<'a>, DecodeError>
31    where
32        'b: 'a,
33    {
34        Ok(match self.byte()? {
35            tag::NULL => ValueRef::Null,
36            tag::FALSE => ValueRef::Bool(false),
37            tag::TRUE => ValueRef::Bool(true),
38            tag::INT => ValueRef::Int(unzigzag(self.varint()?)),
39            tag::FLOAT => ValueRef::Float(f64::from_le_bytes(self.fixed()?)),
40            tag::FLOAT32 => ValueRef::Float(f64::from(f32::from_le_bytes(self.fixed()?))),
41            t @ (tag::FLOATS | tag::FLOATS32) => self.floats_ref(arena, t == tag::FLOATS)?,
42            tag::STR => ValueRef::Str(self.string()?),
43            tag::LIST => {
44                let n = self.count(1)?;
45                self.deeper()?;
46                let items = self.items_ref(arena, stack, n)?;
47                self.depth -= 1;
48                ValueRef::List(items)
49            }
50            tag::MAP => self.map_ref(arena, stack)?,
51            tag::REF => {
52                let (kind, id) = self.reference()?;
53                ValueRef::Ref { kind, id }
54            }
55            tag::BYTES => ValueRef::Bytes(self.length_bytes()?),
56            tag::INTS => self.ints_ref(arena)?,
57            tag::STREAM => {
58                let mut d = Decoder::body(self.stream_body()?);
59                d.depth = self.depth;
60                let n = d.count(1)?;
61                let items = d.items_ref(arena, stack, n)?;
62                d.end()?;
63                ValueRef::List(items)
64            }
65            t => {
66                self.i -= 1;
67                return Err(self.error(format!("unknown tag {t}")));
68            }
69        })
70    }
71
72    /// `n` values gathered on `stack`, then moved into `arena` as one slice.
73    fn items_ref<'a>(
74        &mut self,
75        arena: &'a Bump,
76        stack: &mut Vec<ValueRef<'a>>,
77        n: usize,
78    ) -> Result<&'a [ValueRef<'a>], DecodeError>
79    where
80        'b: 'a,
81    {
82        let start = stack.len();
83        for _ in 0..n {
84            let v = self.value_ref_in(arena, stack)?;
85            stack.push(v);
86        }
87        let items = arena.alloc_slice_copy(&stack[start..]);
88        stack.truncate(start);
89        Ok(items)
90    }
91
92    fn map_ref<'a>(
93        &mut self,
94        arena: &'a Bump,
95        stack: &mut Vec<ValueRef<'a>>,
96    ) -> Result<ValueRef<'a>, DecodeError>
97    where
98        'b: 'a,
99    {
100        let n = self.count(MAP_ENTRY_MIN)?;
101        self.deeper()?;
102        let mut entries = bumpalo::collections::Vec::with_capacity_in(n, arena);
103        let mut seen = SeenKeys::default();
104        for _ in 0..n {
105            let at = self.i;
106            let k = self.string()?;
107            if !seen.insert(k) {
108                return Err(DecodeError::duplicate_key(k, at));
109            }
110            entries.push((k, self.value_ref_in(arena, stack)?));
111        }
112        self.depth -= 1;
113        Ok(ValueRef::Map(MapRef(entries.into_bump_slice())))
114    }
115
116    fn ints_ref<'a>(&mut self, arena: &'a Bump) -> Result<ValueRef<'a>, DecodeError> {
117        let n = self.count(1)?;
118        let mut items = bumpalo::collections::Vec::with_capacity_in(n, arena);
119        for _ in 0..n {
120            items.push(ValueRef::Int(unzigzag(self.varint()?)));
121        }
122        Ok(ValueRef::List(items.into_bump_slice()))
123    }
124
125    /// A list of floats: eight bytes each (`wide`) or four.
126    fn floats_ref<'a>(&mut self, arena: &'a Bump, wide: bool) -> Result<ValueRef<'a>, DecodeError> {
127        let items: Vec<ValueRef<'a>> = if wide {
128            self.packed_floats::<F64_BYTES>()?
129                .map(|f| ValueRef::Float(f64::from_le_bytes(*f)))
130                .collect()
131        } else {
132            self.packed_floats::<F32_BYTES>()?
133                .map(|f| ValueRef::Float(f64::from(f32::from_le_bytes(*f))))
134                .collect()
135        };
136        Ok(ValueRef::List(arena.alloc_slice_copy(&items)))
137    }
138}