facet_msgpack/
to_msgpack.rs

1use facet_core::Facet;
2use facet_reflect::Peek;
3use log::trace;
4use std::io::{self, Write};
5
6/// Serializes any Facet type to MessagePack bytes
7pub fn to_vec<T: Facet>(value: &T) -> Vec<u8> {
8    let mut buffer = Vec::new();
9    let peek = Peek::new(value);
10    serialize(peek, &mut buffer).unwrap();
11    buffer
12}
13
14/// Serializes any Facet type to a writer in MessagePack format
15fn serialize<W: Write>(peek: Peek<'_>, writer: &mut W) -> io::Result<()> {
16    match peek {
17        Peek::Value(pv) => {
18            trace!("Serializing scalar");
19            if pv.shape().is_type::<String>() {
20                let value = unsafe { pv.data().as_ref::<String>() };
21                write_str(writer, value)
22            } else if pv.shape().is_type::<u64>() {
23                let value = unsafe { pv.data().as_ref::<u64>() };
24                write_u64(writer, *value)
25            } else if pv.shape().is_type::<u32>() {
26                let value = unsafe { pv.data().as_ref::<u32>() };
27                write_u32(writer, *value)
28            } else if pv.shape().is_type::<u16>() {
29                let value = unsafe { pv.data().as_ref::<u16>() };
30                write_u16(writer, *value)
31            } else if pv.shape().is_type::<u8>() {
32                let value = unsafe { pv.data().as_ref::<u8>() };
33                write_u8(writer, *value)
34            } else if pv.shape().is_type::<i64>() {
35                let value = unsafe { pv.data().as_ref::<i64>() };
36                write_i64(writer, *value)
37            } else if pv.shape().is_type::<i32>() {
38                let value = unsafe { pv.data().as_ref::<i32>() };
39                write_i32(writer, *value)
40            } else if pv.shape().is_type::<i16>() {
41                let value = unsafe { pv.data().as_ref::<i16>() };
42                write_i16(writer, *value)
43            } else if pv.shape().is_type::<i8>() {
44                let value = unsafe { pv.data().as_ref::<i8>() };
45                write_i8(writer, *value)
46            } else {
47                todo!("Unsupported scalar type: {}", pv.shape())
48            }
49        }
50        Peek::Struct(ps) => {
51            trace!("Serializing struct");
52
53            // Write map header
54            let fields: Vec<_> = ps.fields().collect();
55            write_map_len(writer, fields.len())?;
56
57            // Write fields
58            for (name, field_peek) in fields {
59                write_str(writer, name)?;
60                serialize(field_peek, writer)?;
61            }
62            Ok(())
63        }
64        _ => {
65            todo!("Unsupported type: {:?}", peek)
66        }
67    }
68}
69
70fn write_str<W: Write>(writer: &mut W, s: &str) -> io::Result<()> {
71    let bytes = s.as_bytes();
72    let len = bytes.len();
73
74    match len {
75        0..=31 => {
76            // fixstr
77            writer.write_all(&[(0xa0 | len as u8)])?;
78        }
79        32..=255 => {
80            // str8
81            writer.write_all(&[0xd9, len as u8])?;
82        }
83        256..=65535 => {
84            // str16
85            writer.write_all(&[0xda])?;
86            writer.write_all(&(len as u16).to_be_bytes())?;
87        }
88        _ => {
89            // str32
90            writer.write_all(&[0xdb])?;
91            writer.write_all(&(len as u32).to_be_bytes())?;
92        }
93    }
94    writer.write_all(bytes)
95}
96
97fn write_u8<W: Write>(writer: &mut W, n: u8) -> io::Result<()> {
98    match n {
99        0..=127 => {
100            // positive fixint
101            writer.write_all(&[n])
102        }
103        _ => {
104            // uint8
105            writer.write_all(&[0xcc, n])
106        }
107    }
108}
109
110fn write_u16<W: Write>(writer: &mut W, n: u16) -> io::Result<()> {
111    match n {
112        0..=127 => {
113            // positive fixint
114            writer.write_all(&[n as u8])
115        }
116        128..=255 => {
117            // uint8
118            writer.write_all(&[0xcc, n as u8])
119        }
120        _ => {
121            // uint16
122            writer.write_all(&[0xcd])?;
123            writer.write_all(&n.to_be_bytes())
124        }
125    }
126}
127
128fn write_u32<W: Write>(writer: &mut W, n: u32) -> io::Result<()> {
129    match n {
130        0..=127 => {
131            // positive fixint
132            writer.write_all(&[n as u8])
133        }
134        128..=255 => {
135            // uint8
136            writer.write_all(&[0xcc, n as u8])
137        }
138        256..=65535 => {
139            // uint16
140            writer.write_all(&[0xcd])?;
141            writer.write_all(&(n as u16).to_be_bytes())
142        }
143        _ => {
144            // uint32
145            writer.write_all(&[0xce])?;
146            writer.write_all(&n.to_be_bytes())
147        }
148    }
149}
150
151fn write_u64<W: Write>(writer: &mut W, n: u64) -> io::Result<()> {
152    match n {
153        0..=127 => {
154            // positive fixint
155            writer.write_all(&[n as u8])
156        }
157        128..=255 => {
158            // uint8
159            writer.write_all(&[0xcc, n as u8])
160        }
161        256..=65535 => {
162            // uint16
163            writer.write_all(&[0xcd])?;
164            writer.write_all(&(n as u16).to_be_bytes())
165        }
166        65536..=4294967295 => {
167            // uint32
168            writer.write_all(&[0xce])?;
169            writer.write_all(&(n as u32).to_be_bytes())
170        }
171        _ => {
172            // uint64
173            writer.write_all(&[0xcf])?;
174            writer.write_all(&n.to_be_bytes())
175        }
176    }
177}
178
179fn write_i8<W: Write>(writer: &mut W, n: i8) -> io::Result<()> {
180    match n {
181        -32..=-1 => {
182            // negative fixint
183            writer.write_all(&[n as u8])
184        }
185        -128..=-33 => {
186            // int8
187            writer.write_all(&[0xd0, n as u8])
188        }
189        0..=127 => {
190            // positive fixint
191            writer.write_all(&[n as u8])
192        }
193    }
194}
195
196fn write_i16<W: Write>(writer: &mut W, n: i16) -> io::Result<()> {
197    match n {
198        -32..=-1 => {
199            // negative fixint
200            writer.write_all(&[n as u8])
201        }
202        -128..=-33 => {
203            // int8
204            writer.write_all(&[0xd0, n as u8])
205        }
206        -32768..=-129 => {
207            // int16
208            writer.write_all(&[0xd1])?;
209            writer.write_all(&n.to_be_bytes())
210        }
211        0..=127 => {
212            // positive fixint
213            writer.write_all(&[n as u8])
214        }
215        128..=255 => {
216            // uint8
217            writer.write_all(&[0xcc, n as u8])
218        }
219        256..=32767 => {
220            // uint16
221            writer.write_all(&[0xcd])?;
222            writer.write_all(&(n as u16).to_be_bytes())
223        }
224    }
225}
226
227fn write_i32<W: Write>(writer: &mut W, n: i32) -> io::Result<()> {
228    match n {
229        -32..=-1 => {
230            // negative fixint
231            writer.write_all(&[n as u8])
232        }
233        -128..=-33 => {
234            // int8
235            writer.write_all(&[0xd0, n as u8])
236        }
237        -32768..=-129 => {
238            // int16
239            writer.write_all(&[0xd1])?;
240            writer.write_all(&(n as i16).to_be_bytes())
241        }
242        -2147483648..=-32769 => {
243            // int32
244            writer.write_all(&[0xd2])?;
245            writer.write_all(&n.to_be_bytes())
246        }
247        0..=127 => {
248            // positive fixint
249            writer.write_all(&[n as u8])
250        }
251        128..=255 => {
252            // uint8
253            writer.write_all(&[0xcc, n as u8])
254        }
255        256..=65535 => {
256            // uint16
257            writer.write_all(&[0xcd])?;
258            writer.write_all(&(n as u16).to_be_bytes())
259        }
260        65536..=2147483647 => {
261            // uint32
262            writer.write_all(&[0xce])?;
263            writer.write_all(&(n as u32).to_be_bytes())
264        }
265    }
266}
267
268fn write_i64<W: Write>(writer: &mut W, n: i64) -> io::Result<()> {
269    match n {
270        -32..=-1 => {
271            // negative fixint
272            writer.write_all(&[n as u8])
273        }
274        -128..=-33 => {
275            // int8
276            writer.write_all(&[0xd0, n as u8])
277        }
278        -32768..=-129 => {
279            // int16
280            writer.write_all(&[0xd1])?;
281            writer.write_all(&(n as i16).to_be_bytes())
282        }
283        -2147483648..=-32769 => {
284            // int32
285            writer.write_all(&[0xd2])?;
286            writer.write_all(&(n as i32).to_be_bytes())
287        }
288        i64::MIN..=-2147483649 => {
289            // int64
290            writer.write_all(&[0xd3])?;
291            writer.write_all(&n.to_be_bytes())
292        }
293        0..=127 => {
294            // positive fixint
295            writer.write_all(&[n as u8])
296        }
297        128..=255 => {
298            // uint8
299            writer.write_all(&[0xcc, n as u8])
300        }
301        256..=65535 => {
302            // uint16
303            writer.write_all(&[0xcd])?;
304            writer.write_all(&(n as u16).to_be_bytes())
305        }
306        65536..=4294967295 => {
307            // uint32
308            writer.write_all(&[0xce])?;
309            writer.write_all(&(n as u32).to_be_bytes())
310        }
311        4294967296..=i64::MAX => {
312            // uint64
313            writer.write_all(&[0xcf])?;
314            writer.write_all(&(n as u64).to_be_bytes())
315        }
316    }
317}
318
319fn write_map_len<W: Write>(writer: &mut W, len: usize) -> io::Result<()> {
320    match len {
321        0..=15 => {
322            // fixmap
323            writer.write_all(&[(0x80 | len as u8)])
324        }
325        16..=65535 => {
326            // map16
327            writer.write_all(&[0xde])?;
328            writer.write_all(&(len as u16).to_be_bytes())
329        }
330        _ => {
331            // map32
332            writer.write_all(&[0xdf])?;
333            writer.write_all(&(len as u32).to_be_bytes())
334        }
335    }
336}