facet_msgpack/
to_msgpack.rs

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