substrate_data/wire/binary/write/
writer.rs1use super::shape_cache::ShapeCache;
4use crate::binary::{
5 INLINE_INT_MAX, INLINE_INT_MIN, MAGIC, NEW_STRING, STR_INDEX_COUNT, VERSION, tag, varint,
6 zigzag,
7};
8use crate::wire::binary::layout::{narrow, narrows};
9use crate::wire::binary::table::interner::Interner;
10use crate::wire::binary::table::shape_table::ShapeTable;
11
12pub(crate) const START_BYTES: usize = 256;
14
15#[derive(Debug)]
26pub struct Writer {
27 pub(in crate::wire::binary) out: Vec<u8>,
28 pub(in crate::wire::binary) strings: Interner,
30 pub(in crate::wire::binary) shapes: ShapeTable,
32 pub(in crate::wire::binary) cache: ShapeCache,
34}
35
36impl Default for Writer {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl Writer {
43 #[must_use]
45 pub fn new() -> Self {
46 let mut out = Vec::with_capacity(START_BYTES);
47 out.extend_from_slice(MAGIC);
48 out.push(VERSION);
49 Self::over(out)
50 }
51
52 fn over(out: Vec<u8>) -> Self {
54 Writer {
55 out,
56 strings: Interner::new(),
57 shapes: ShapeTable::default(),
58 cache: ShapeCache::default(),
59 }
60 }
61
62 pub(crate) fn appending(mut out: Vec<u8>) -> Self {
65 out.extend_from_slice(MAGIC);
66 out.push(VERSION);
67 Self::over(out)
68 }
69
70 pub(crate) fn restart(&mut self, prefix: usize) {
73 self.out.clear();
74 self.out.resize(prefix, 0);
75 self.out.extend_from_slice(MAGIC);
76 self.out.push(VERSION);
77 self.strings.clear();
78 self.shapes.clear();
79 self.cache.clear();
80 }
81
82 pub(crate) fn buffer_mut(&mut self) -> &mut Vec<u8> {
84 &mut self.out
85 }
86
87 pub fn null(&mut self) -> &mut Self {
89 self.out.push(tag::NULL);
90 self
91 }
92
93 pub fn bool(&mut self, b: bool) -> &mut Self {
95 self.out.push(if b { tag::TRUE } else { tag::FALSE });
96 self
97 }
98
99 #[inline]
101 pub fn int(&mut self, n: i64) -> &mut Self {
102 let inline = u8::try_from(n.wrapping_sub(INLINE_INT_MIN))
103 .ok()
104 .filter(|&at| i64::from(at) <= INLINE_INT_MAX - INLINE_INT_MIN);
105 if let Some(at) = inline {
106 self.out.push(tag::INT_INLINE + at);
107 return self;
108 }
109 self.out.push(tag::INT);
110 varint(&mut self.out, zigzag(n));
111 self
112 }
113
114 pub fn float(&mut self, f: f64) -> &mut Self {
117 if narrows(f) {
118 return self.float32(narrow(f));
119 }
120 self.out.push(tag::FLOAT);
121 self.out.extend_from_slice(&f.to_le_bytes());
122 self
123 }
124
125 pub fn float32(&mut self, f: f32) -> &mut Self {
127 self.out.push(tag::FLOAT32);
128 self.out.extend_from_slice(&f.to_le_bytes());
129 self
130 }
131
132 pub fn str(&mut self, s: &str) -> &mut Self {
135 let found = self.strings.lookup(&self.out, s);
136 if let Ok(i) = found
137 && let Ok(at) = u8::try_from(i)
138 && at < STR_INDEX_COUNT
139 {
140 self.out.push(tag::STR_INDEX + at);
141 return self;
142 }
143 self.out.push(tag::STR);
144 self.put_string(s, found);
145 self
146 }
147
148 pub fn bytes(&mut self, b: &[u8]) -> &mut Self {
150 self.out.push(tag::BYTES);
151 varint(&mut self.out, b.len() as u64);
152 self.out.extend_from_slice(b);
153 self
154 }
155
156 pub fn list(&mut self, len: usize) -> &mut Self {
158 self.out.push(tag::LIST);
159 varint(&mut self.out, len as u64);
160 self
161 }
162
163 pub(crate) fn stream_body(&mut self, len: usize, items: &[u8]) -> &mut Self {
165 let mut count = Vec::new();
166 varint(&mut count, len as u64);
167 self.out.push(tag::STREAM);
168 let body = u32::try_from(count.len() + items.len()).unwrap_or(u32::MAX);
169 self.out.extend_from_slice(&body.to_le_bytes());
170 self.out.extend_from_slice(&count);
171 self.out.extend_from_slice(items);
172 self
173 }
174
175 pub(crate) fn body() -> Self {
177 Self::over(Vec::with_capacity(START_BYTES))
178 }
179
180 pub fn map(&mut self, len: usize) -> &mut Self {
184 self.out.push(tag::MAP);
185 varint(&mut self.out, len as u64);
186 self
187 }
188
189 pub fn key(&mut self, k: &str) -> &mut Self {
191 self.string(k);
192 self
193 }
194
195 #[must_use]
197 pub fn finish(self) -> Vec<u8> {
198 self.out
199 }
200
201 pub(in crate::wire::binary) fn string(&mut self, s: &str) -> usize {
203 let found = self.strings.find(&self.out, s);
204 self.put_string(s, found)
205 }
206
207 #[inline]
209 pub(in crate::wire::binary) fn put_string(
210 &mut self,
211 s: &str,
212 found: Result<usize, Option<u32>>,
213 ) -> usize {
214 match found {
215 Ok(i) => {
216 varint(&mut self.out, (i as u64) << 1);
217 i
218 }
219 Err(hash) => {
220 varint(&mut self.out, ((s.len() as u64) << 1) | NEW_STRING);
221 let at = self.out.len();
222 self.out.extend_from_slice(s.as_bytes());
223 self.strings.add(&self.out, s, at, hash)
224 }
225 }
226 }
227}