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