facet_msgpack/
to_msgpack.rs

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