web3api_wasm_rs/msgpack/
write_encoder.rs

1use super::{error::EncodeError, DataView, Format, Write, ExtensionType};
2use crate::{BigInt, BigNumber, JSON, Context};
3use byteorder::{BigEndian, WriteBytesExt};
4use core::hash::Hash;
5use std::{collections::BTreeMap, io::Write as StdioWrite};
6
7#[derive(Debug)]
8pub struct WriteEncoder {
9    pub(crate) context: Context,
10    pub(crate) view: DataView,
11}
12
13impl WriteEncoder {
14    pub fn new(buf: &[u8], context: Context) -> Self {
15        Self {
16            context: context.clone(),
17            view: DataView::new(buf, context).expect("Error creating new data view"),
18        }
19    }
20
21    pub fn get_buffer(&self) -> Vec<u8> {
22        self.view.get_buffer()
23    }
24
25    pub fn write_negative_fixed_int(&mut self, value: i8) -> Result<(), EncodeError> {
26        // From 0xe0 (0b11100000) taking last 5 bits, to 0xff (0b11111111), taking last 5 bits
27        assert!(-31 <= value && value <= 0);
28        Format::set_format(self, Format::NegativeFixInt(value))
29            .map_err(|e| EncodeError::FormatWriteError(e.to_string()))
30    }
31
32    pub fn write_positive_fixed_int(&mut self, value: u8) -> Result<(), EncodeError> {
33        assert!(value < 128);
34        Format::set_format(self, Format::PositiveFixInt(value))
35            .map_err(|e| EncodeError::FormatWriteError(e.to_string()))
36    }
37
38    /// Encodes a `u64` value into the buffer using the most efficient representation.
39    ///
40    /// The MessagePack spec requires that the serializer should use
41    /// the format which represents the data in the smallest number of bytes.
42    #[doc(hidden)]
43    pub fn write_u64(&mut self, value: &u64) -> Result<(), EncodeError> {
44        let val = *value;
45        if val < 1 << 7 {
46            Ok(self.write_positive_fixed_int(val as u8)?)
47        } else if val <= u8::MAX as u64 {
48            Format::set_format(self, Format::Uint8)?;
49            Ok(WriteBytesExt::write_u8(self, val as u8)?)
50        } else if val <= u16::MAX as u64 {
51            Format::set_format(self, Format::Uint16)?;
52            Ok(WriteBytesExt::write_u16::<BigEndian>(self, val as u16)?)
53        } else if val <= u32::MAX as u64 {
54            Format::set_format(self, Format::Uint32)?;
55            Ok(WriteBytesExt::write_u32::<BigEndian>(self, val as u32)?)
56        } else {
57            Format::set_format(self, Format::Uint64)?;
58            Ok(WriteBytesExt::write_u64::<BigEndian>(self, val as u64)?)
59        }
60    }
61
62    /// Encodes an `i64` value into the buffer using the most efficient representation.
63    ///
64    /// The MessagePack spec requires that the serializer should use
65    /// the format which represents the data in the smallest number of bytes, with the exception of
66    /// sized/unsized types.
67    #[doc(hidden)]
68    pub fn write_i64(&mut self, value: &i64) -> Result<(), EncodeError> {
69        let val = *value;
70
71        if val >= 0 && val < 1 << 7 {
72          Ok(self.write_positive_fixed_int(val as u8)?)
73        } else if val < 0 && val >= -(1 << 5) {
74          Ok(self.write_negative_fixed_int(val as i8)?)
75        } else if val <= i8::MAX as i64 && val >= i8::MIN as i64 {
76          Format::set_format(self, Format::Int8)?;
77          Ok(WriteBytesExt::write_i8(self, val as i8)?)
78        } else if val <= i16::MAX as i64 && val >= i16::MIN as i64 {
79          Format::set_format(self, Format::Int16)?;
80          Ok(WriteBytesExt::write_i16::<BigEndian>(self, val as i16)?)
81        } else if val <= i32::MAX as i64 && val >= i32::MIN as i64 {
82          Format::set_format(self, Format::Int32)?;
83          Ok(WriteBytesExt::write_i32::<BigEndian>(self, val as i32)?)
84        } else {
85          Format::set_format(self, Format::Int64)?;
86          Ok(WriteBytesExt::write_i64::<BigEndian>(self, val as i64)?)
87        }
88    }
89}
90
91impl StdioWrite for WriteEncoder {
92    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
93        self.view.buffer.write(buf)
94    }
95
96    fn flush(&mut self) -> std::io::Result<()> {
97        self.view.buffer.flush()
98    }
99}
100
101impl Write for WriteEncoder {
102    fn write_nil(&mut self) -> Result<(), EncodeError> {
103        Format::set_format(self, Format::Nil).map_err(|e| EncodeError::NilWriteError(e.to_string()))
104    }
105
106    fn write_bool(&mut self, value: &bool) -> Result<(), EncodeError> {
107        let format = if *value { Format::True } else { Format::False };
108        Format::set_format(self, format).map_err(|e| EncodeError::BooleanWriteError(e.to_string()))
109    }
110
111    fn write_i8(&mut self, value: &i8) -> Result<(), EncodeError> {
112        self.write_i64(&(*value as i64))
113            .map_err(|e| EncodeError::Int8WriteError(e.to_string()))
114    }
115
116    fn write_i16(&mut self, value: &i16) -> Result<(), EncodeError> {
117        self.write_i64(&(*value as i64))
118            .map_err(|e| EncodeError::Int16WriteError(e.to_string()))
119    }
120
121    fn write_i32(&mut self, value: &i32) -> Result<(), EncodeError> {
122        self.write_i64(&(*value as i64))
123            .map_err(|e| EncodeError::Int32WriteError(e.to_string()))
124    }
125
126    fn write_u8(&mut self, value: &u8) -> Result<(), EncodeError> {
127        self.write_u64(&(*value as u64))
128            .map_err(|e| EncodeError::Uint8WriteError(e.to_string()))
129    }
130
131    fn write_u16(&mut self, value: &u16) -> Result<(), EncodeError> {
132        self.write_u64(&(*value as u64))
133            .map_err(|e| EncodeError::Uint16WriteError(e.to_string()))
134    }
135
136    fn write_u32(&mut self, value: &u32) -> Result<(), EncodeError> {
137        self.write_u64(&(*value as u64))
138            .map_err(|e| EncodeError::Uint32WriteError(e.to_string()))
139    }
140
141    fn write_f32(&mut self, value: &f32) -> Result<(), EncodeError> {
142        Format::set_format(self, Format::Float32)?;
143        WriteBytesExt::write_f32::<BigEndian>(self, *value)
144            .map_err(|e| EncodeError::Float32WriteError(e.to_string()))
145    }
146
147    fn write_f64(&mut self, value: &f64) -> Result<(), EncodeError> {
148        Format::set_format(self, Format::Float64)?;
149        WriteBytesExt::write_f64::<BigEndian>(self, *value)
150            .map_err(|e| EncodeError::Float64WriteError(e.to_string()))
151    }
152
153    fn write_string_length(&mut self, length: &u32) -> Result<(), EncodeError> {
154        let length = *length;
155        if length < 32 {
156            Format::set_format(self, Format::FixStr(length as u8))?;
157        } else if length <= u8::MAX as u32 {
158            Format::set_format(self, Format::Str8)?;
159            WriteBytesExt::write_u8(self, length as u8)?;
160        } else if length <= u16::MAX as u32 {
161            Format::set_format(self, Format::Str16)?;
162            WriteBytesExt::write_u16::<BigEndian>(self, length as u16)?;
163        } else {
164            Format::set_format(self, Format::Str32)?;
165            WriteBytesExt::write_u32::<BigEndian>(self, length)?;
166        }
167        Ok(())
168    }
169
170    fn write_string(&mut self, value: &str) -> Result<(), EncodeError> {
171        self.write_string_length(&(value.len() as u32))?;
172        self.write_all(value.as_bytes())
173            .map_err(|e| EncodeError::StrWriteError(e.to_string()))
174    }
175
176    fn write_bytes_length(&mut self, length: &u32) -> Result<(), EncodeError> {
177        let length = *length;
178        if length <= u8::MAX as u32 {
179            Format::set_format(self, Format::Bin8)?;
180            WriteBytesExt::write_u8(self, length as u8)?;
181        } else if length <= u16::MAX as u32 {
182            Format::set_format(self, Format::Bin16)?;
183            WriteBytesExt::write_u16::<BigEndian>(self, length as u16)?;
184        } else {
185            Format::set_format(self, Format::Bin32)?;
186            WriteBytesExt::write_u32::<BigEndian>(self, length)?;
187        }
188        Ok(())
189    }
190
191    fn write_bytes(&mut self, buf: &[u8]) -> Result<(), EncodeError> {
192        if buf.is_empty() {
193            return self.write_nil();
194        }
195        self.write_bytes_length(&(buf.len() as u32))?;
196        self.write_all(buf)
197            .map_err(|e| EncodeError::BinWriteError(e.to_string()))
198    }
199
200    fn write_bigint(&mut self, value: &BigInt) -> Result<(), EncodeError> {
201        self.write_string(&value.to_string())
202            .map_err(|e| EncodeError::BigIntWriteError(e.to_string()))
203    }
204
205    fn write_bignumber(&mut self, value: &BigNumber) -> Result<(), EncodeError> {
206        self.write_string(&value.to_string())
207            .map_err(|e| EncodeError::BigIntWriteError(e.to_string()))
208    }
209
210    fn write_json(&mut self, value: &JSON::Value) -> Result<(), EncodeError> {
211        let json_str = JSON::to_string(value)?;
212        self.write_string(&json_str)
213            .map_err(|e| EncodeError::JSONWriteError(e.to_string()))
214    }
215
216    fn write_array_length(&mut self, length: &u32) -> Result<(), EncodeError> {
217        let length = *length;
218        if length < 16 {
219            Format::set_format(self, Format::FixArray(length as u8))?;
220        } else if length <= u16::MAX as u32 {
221            Format::set_format(self, Format::Array16)?;
222            WriteBytesExt::write_u16::<BigEndian>(self, length as u16)?;
223        } else {
224            Format::set_format(self, Format::Array32)?;
225            WriteBytesExt::write_u32::<BigEndian>(self, length)?;
226        }
227        Ok(())
228    }
229
230    fn write_array<T: Clone>(
231        &mut self,
232        array: &[T],
233        mut item_writer: impl FnMut(&mut Self, &T) -> Result<(), EncodeError>,
234    ) -> Result<(), EncodeError> {
235        self.write_array_length(&(array.len() as u32))?;
236        for element in array {
237            item_writer(self, element)?;
238        }
239        Ok(())
240    }
241
242    fn write_map_length(&mut self, length: &u32) -> Result<(), EncodeError> {
243        let length = *length;
244        if length < 16 {
245            Format::set_format(self, Format::FixMap(length as u8))?;
246        } else if length <= u16::MAX as u32 {
247            Format::set_format(self, Format::Map16)?;
248            WriteBytesExt::write_u16::<BigEndian>(self, length as u16)?;
249        } else {
250            Format::set_format(self, Format::Map32)?;
251            WriteBytesExt::write_u32::<BigEndian>(self, length)?;
252        }
253        Ok(())
254    }
255
256    fn write_map<K, V: Clone>(
257        &mut self,
258        map: &BTreeMap<K, V>,
259        mut key_writer: impl FnMut(&mut Self, &K) -> Result<(), EncodeError>,
260        mut val_writer: impl FnMut(&mut Self, &V) -> Result<(), EncodeError>,
261    ) -> Result<(), EncodeError>
262    where
263        K: Clone + Eq + Hash + Ord,
264    {
265        self.write_map_length(&(map.len() as u32))?;
266        let keys: Vec<_> = map.keys().into_iter().collect();
267        for key in keys {
268            let value = &map[key];
269            key_writer(self, key)?;
270            val_writer(self, value)?;
271        }
272        Ok(())
273    }
274
275    fn write_ext_generic_map<K, V: Clone>(
276        &mut self,
277        map: &BTreeMap<K, V>,
278        mut key_writer: impl FnMut(&mut Self, &K) -> Result<(), EncodeError>,
279        mut val_writer: impl FnMut(&mut Self, &V) -> Result<(), EncodeError>,
280    ) -> Result<(), EncodeError>
281    where
282        K: Clone + Eq + Hash + Ord,
283    {
284        let mut encoder = WriteEncoder::new(&[], self.context.clone());
285        encoder.write_map(map, key_writer, val_writer)?;
286
287        let buf = encoder.get_buffer();
288        let bytelength = buf.len();
289
290        // Encode the extension format + bytelength
291        if bytelength <= u8::MAX as usize {
292            Format::set_format(self, Format::Ext8)?;
293            WriteBytesExt::write_u8(self, bytelength.try_into().unwrap())?;
294        } else if bytelength <= u16::MAX as usize {
295            Format::set_format(self, Format::Ext16)?;
296            WriteBytesExt::write_u16::<BigEndian>(self, bytelength.try_into().unwrap())?;
297        } else {
298            Format::set_format(self, Format::Ext32)?;
299            WriteBytesExt::write_u32::<BigEndian>(self, bytelength.try_into().unwrap())?;
300        }
301
302        // Set the extension type
303        WriteBytesExt::write_u8(self, ExtensionType::GenericMap.to_u8())?;
304
305        // Copy the map's encoded buffer
306        self.view.buffer.write_all(&buf)?;
307
308        Ok(())
309    }
310
311    fn write_nullable_bool(&mut self, value: &Option<bool>) -> Result<(), EncodeError> {
312        match value {
313            None => Write::write_nil(self),
314            Some(v) => Write::write_bool(self, v),
315        }
316    }
317
318    fn write_nullable_i8(&mut self, value: &Option<i8>) -> Result<(), EncodeError> {
319        match value {
320            None => Write::write_nil(self),
321            Some(v) => Write::write_i8(self, v),
322        }
323    }
324
325    fn write_nullable_i16(&mut self, value: &Option<i16>) -> Result<(), EncodeError> {
326        match value {
327            None => Write::write_nil(self),
328            Some(v) => Write::write_i16(self, v),
329        }
330    }
331
332    fn write_nullable_i32(&mut self, value: &Option<i32>) -> Result<(), EncodeError> {
333        match value {
334            None => Write::write_nil(self),
335            Some(v) => Write::write_i32(self, v),
336        }
337    }
338
339    fn write_nullable_u8(&mut self, value: &Option<u8>) -> Result<(), EncodeError> {
340        match value {
341            None => Write::write_nil(self),
342            Some(v) => Write::write_u8(self, v),
343        }
344    }
345
346    fn write_nullable_u16(&mut self, value: &Option<u16>) -> Result<(), EncodeError> {
347        match value {
348            None => Write::write_nil(self),
349            Some(v) => Write::write_u16(self, v),
350        }
351    }
352
353    fn write_nullable_u32(&mut self, value: &Option<u32>) -> Result<(), EncodeError> {
354        match value {
355            None => Write::write_nil(self),
356            Some(v) => Write::write_u32(self, v),
357        }
358    }
359
360    fn write_nullable_f32(&mut self, value: &Option<f32>) -> Result<(), EncodeError> {
361        match value {
362            None => Write::write_nil(self),
363            Some(v) => Write::write_f32(self, v),
364        }
365    }
366
367    fn write_nullable_f64(&mut self, value: &Option<f64>) -> Result<(), EncodeError> {
368        match value {
369            None => Write::write_nil(self),
370            Some(v) => Write::write_f64(self, v),
371        }
372    }
373
374    fn write_nullable_string(&mut self, value: &Option<String>) -> Result<(), EncodeError> {
375        match value {
376            None => Write::write_nil(self),
377            Some(s) => Write::write_string(self, s),
378        }
379    }
380
381    fn write_nullable_bytes(&mut self, value: &Option<Vec<u8>>) -> Result<(), EncodeError> {
382        match value {
383            None => Write::write_nil(self),
384            Some(bytes) => Write::write_bytes(self, bytes),
385        }
386    }
387
388    fn write_nullable_bigint(&mut self, value: &Option<BigInt>) -> Result<(), EncodeError> {
389        match value {
390            None => Write::write_nil(self),
391            Some(bigint) => Write::write_bigint(self, bigint),
392        }
393    }
394
395    fn write_nullable_bignumber(&mut self, value: &Option<BigNumber>) -> Result<(), EncodeError> {
396        match value {
397            None => Write::write_nil(self),
398            Some(bignumber) => Write::write_bignumber(self, bignumber)
399        }
400    }
401
402    fn write_nullable_json(&mut self, value: &Option<JSON::Value>) -> Result<(), EncodeError> {
403        match value {
404            None => Write::write_nil(self),
405            Some(json) => Write::write_json(self, json),
406        }
407    }
408
409    fn write_nullable_array<T: Clone>(
410        &mut self,
411        opt_array: &Option<Vec<T>>,
412        item_writer: impl FnMut(&mut Self, &T) -> Result<(), EncodeError>,
413    ) -> Result<(), EncodeError> {
414        match opt_array {
415            None => Write::write_nil(self),
416            Some(array) => Write::write_array(self, array, item_writer),
417        }
418    }
419
420    fn write_nullable_map<K, V: Clone>(
421        &mut self,
422        opt_map: &Option<BTreeMap<K, V>>,
423        key_writer: impl FnMut(&mut Self, &K) -> Result<(), EncodeError>,
424        val_writer: impl FnMut(&mut Self, &V) -> Result<(), EncodeError>,
425    ) -> Result<(), EncodeError>
426    where
427        K: Clone + Eq + Hash + Ord,
428    {
429        match opt_map {
430            None => Write::write_nil(self),
431            Some(map) => Write::write_map(self, map, key_writer, val_writer),
432        }
433    }
434
435    fn write_nullable_ext_generic_map<K, V: Clone>(
436        &mut self,
437        opt_map: &Option<BTreeMap<K, V>>,
438        key_writer: impl FnMut(&mut Self, &K) -> Result<(), EncodeError>,
439        val_writer: impl FnMut(&mut Self, &V) -> Result<(), EncodeError>,
440    ) -> Result<(), EncodeError>
441    where
442        K: Clone + Eq + Hash + Ord,
443    {
444        match opt_map {
445            None => Write::write_nil(self),
446            Some(map) => Write::write_ext_generic_map(self, map, key_writer, val_writer),
447        }
448    }
449
450    fn context(&mut self) -> &mut Context {
451        &mut self.context
452    }
453}