substrate_data/wire/frame/
packer.rs1use super::sizes::{LENGTH_RESERVED, ONE_BYTE_MAX, VARINT_MAX_BYTES};
4use super::{floats, lanes};
5use crate::binary::table::interner::Interner;
6use crate::binary::writer::START_BYTES;
7use crate::binary::{Writer, varint, zigzag};
8use crate::schema::Schema;
9
10pub fn to_frame<T: Schema>(v: &T) -> Vec<u8> {
12 let mut p = Packer::new();
13 v.pack(&mut p);
14 p.finish()
15}
16
17#[derive(Debug)]
19pub struct Packer {
20 out: Vec<u8>,
21 table: Vec<u8>,
22 strings: Interner,
23}
24
25impl Default for Packer {
26 fn default() -> Self {
27 Self::new()
28 }
29}
30
31impl Packer {
32 #[must_use]
34 pub fn new() -> Self {
35 Packer {
36 out: Vec::with_capacity(START_BYTES),
37 table: Vec::new(),
38 strings: Interner::new(),
39 }
40 }
41
42 pub fn put_u(&mut self, n: u64) {
44 varint(&mut self.out, n);
45 }
46
47 pub fn put_i(&mut self, n: i64) {
49 varint(&mut self.out, zigzag(n));
50 }
51
52 pub fn put_bool(&mut self, b: bool) {
54 self.out.push(u8::from(b));
55 }
56
57 pub fn put_f64(&mut self, f: f64) {
59 self.out.extend_from_slice(&f.to_le_bytes());
60 }
61
62 pub fn put_f32(&mut self, f: f32) {
64 self.out.extend_from_slice(&f.to_le_bytes());
65 }
66
67 pub fn put_f64s(&mut self, items: &[f64]) {
70 self.put_u(items.len() as u64);
71 let narrow = floats::fits_f32(items);
72 self.put_bool(narrow);
73 if narrow {
74 floats::put_narrow(&mut self.out, items);
75 } else {
76 floats::put_wide(&mut self.out, items);
77 }
78 }
79
80 pub fn put_uints(&mut self, len: usize, items: impl Iterator<Item = u64> + Clone) {
83 self.put_u(len as u64);
84 let max = items.clone().fold(0, u64::max);
85 let bits = (u64::BITS - max.leading_zeros()).max(1);
86 self.out.push(u8::try_from(bits).unwrap_or(u8::MAX));
87 lanes::pack(&mut self.out, len, bits, items);
88 }
89
90 pub fn put_f32s(&mut self, items: &[f32]) {
92 self.put_u(items.len() as u64);
93 floats::put_f32s(&mut self.out, items);
94 }
95
96 pub fn put_str(&mut self, s: &str) {
98 let i = match self.strings.lookup(&self.table, s) {
99 Ok(i) => i,
100 Err(hash) => {
101 varint(&mut self.table, s.len() as u64);
102 let at = self.table.len();
103 self.table.extend_from_slice(s.as_bytes());
104 self.strings.add(&self.table, s, at, hash)
105 }
106 };
107 self.put_u(i as u64);
108 }
109
110 pub fn put_bytes(&mut self, b: &[u8]) {
112 self.put_u(b.len() as u64);
113 self.out.extend_from_slice(b);
114 }
115
116 pub fn put_tagged<T: Schema>(&mut self, v: &T) {
119 let mut w = Writer::body();
120 v.encode(&mut w);
121 self.put_bytes(&w.finish());
122 }
123
124 pub fn begin(&mut self) -> usize {
126 let at = self.out.len();
127 self.out.extend_from_slice(&[0; LENGTH_RESERVED]);
128 at
129 }
130
131 pub fn begin_list(&mut self, len: usize) -> usize {
135 self.put_u(len as u64);
136 self.begin()
137 }
138
139 pub fn end(&mut self, at: usize) {
141 let len = self.out.len() - at - LENGTH_RESERVED;
142 if let Ok(byte) = u8::try_from(len)
143 && len <= ONE_BYTE_MAX
144 {
145 self.out[at] = byte;
146 return;
147 }
148 let end = self.out.len();
151 varint(&mut self.out, len as u64);
152 let mut length = [0; VARINT_MAX_BYTES];
153 let used = self.out.len() - end;
154 length[..used].copy_from_slice(&self.out[end..]);
155 self.out.truncate(end);
156 self.out.splice(at..=at, length[..used].iter().copied());
157 }
158
159 #[must_use]
161 pub fn finish(mut self) -> Vec<u8> {
162 self.seal();
163 self.out
164 }
165
166 fn seal(&mut self) {
168 let table_len = self.table.len();
169 self.out.extend_from_slice(&self.table);
170 let at = self.out.len();
172 varint(&mut self.out, table_len as u64);
173 self.out[at..].reverse();
174 }
175
176 pub fn with_frame<T: Schema, R>(&mut self, v: &T, f: impl FnOnce(&[u8]) -> R) -> R {
179 self.clear();
180 v.pack(self);
181 self.seal();
182 let out = f(&self.out);
183 self.clear();
184 out
185 }
186
187 fn clear(&mut self) {
189 self.out.clear();
190 self.table.clear();
191 self.strings.clear();
192 }
193}