postcard/ser/
mod.rs

1use crate::error::{Error, Result};
2use crate::ser::flavors::{Cobs, Flavor, Slice};
3use serde::Serialize;
4
5#[cfg(feature = "heapless")]
6use crate::ser::flavors::HVec;
7
8#[cfg(feature = "heapless")]
9use heapless::Vec;
10
11#[cfg(feature = "alloc")]
12use crate::ser::flavors::AllocVec;
13
14#[cfg(feature = "alloc")]
15extern crate alloc;
16
17use crate::ser::serializer::Serializer;
18
19pub mod flavors;
20pub(crate) mod serializer;
21
22/// Serialize a `T` to the given slice, with the resulting slice containing
23/// data in a serialized then COBS encoded format. The terminating sentinel
24/// `0x00` byte is included in the output buffer.
25///
26/// When successful, this function returns the slice containing the
27/// serialized and encoded message.
28///
29/// ## Example
30///
31/// ```rust
32/// use postcard::to_slice_cobs;
33/// let mut buf = [0u8; 32];
34///
35/// let used = to_slice_cobs(&false, &mut buf).unwrap();
36/// assert_eq!(used, &[0x01, 0x01, 0x00]);
37///
38/// let used = to_slice_cobs("1", &mut buf).unwrap();
39/// assert_eq!(used, &[0x03, 0x01, b'1', 0x00]);
40///
41/// let used = to_slice_cobs("Hi!", &mut buf).unwrap();
42/// assert_eq!(used, &[0x05, 0x03, b'H', b'i', b'!', 0x00]);
43///
44/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
45/// let used = to_slice_cobs(data, &mut buf).unwrap();
46/// assert_eq!(used, &[0x03, 0x04, 0x01, 0x03, 0x20, 0x30, 0x00]);
47/// ```
48pub fn to_slice_cobs<'a, 'b, T>(value: &'b T, buf: &'a mut [u8]) -> Result<&'a mut [u8]>
49where
50    T: Serialize + ?Sized,
51{
52    serialize_with_flavor::<T, Cobs<Slice<'a>>, &'a mut [u8]>(
53        value,
54        Cobs::try_new(Slice::new(buf))?,
55    )
56}
57
58/// Serialize a `T` to the given slice, with the resulting slice containing
59/// data in a serialized format.
60///
61/// When successful, this function returns the slice containing the
62/// serialized message
63///
64/// ## Example
65///
66/// ```rust
67/// use postcard::to_slice;
68/// let mut buf = [0u8; 32];
69///
70/// let used = to_slice(&true, &mut buf).unwrap();
71/// assert_eq!(used, &[0x01]);
72///
73/// let used = to_slice("Hi!", &mut buf).unwrap();
74/// assert_eq!(used, &[0x03, b'H', b'i', b'!']);
75///
76/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
77/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
78/// let used = to_slice(data, &mut buf).unwrap();
79/// assert_eq!(used, &[0x04, 0x01, 0x00, 0x20, 0x30]);
80///
81/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
82/// let used = to_slice(data, &mut buf).unwrap();
83/// assert_eq!(used, &[0x01, 0x00, 0x20, 0x30]);
84/// ```
85pub fn to_slice<'a, 'b, T>(value: &'b T, buf: &'a mut [u8]) -> Result<&'a mut [u8]>
86where
87    T: Serialize + ?Sized,
88{
89    serialize_with_flavor::<T, Slice<'a>, &'a mut [u8]>(value, Slice::new(buf))
90}
91
92/// Serialize a `T` to a `heapless::Vec<u8>`, with the `Vec` containing
93/// data in a serialized then COBS encoded format. The terminating sentinel
94/// `0x00` byte is included in the output `Vec`.
95///
96/// ## Example
97///
98/// ```rust
99/// use postcard::to_vec_cobs;
100/// use heapless::Vec;
101/// use core::ops::Deref;
102///
103/// let ser: Vec<u8, 32> = to_vec_cobs(&false).unwrap();
104/// assert_eq!(ser.deref(), &[0x01, 0x01, 0x00]);
105///
106/// let ser: Vec<u8, 32> = to_vec_cobs("Hi!").unwrap();
107/// assert_eq!(ser.deref(), &[0x05, 0x03, b'H', b'i', b'!', 0x00]);
108///
109/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
110/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
111/// let ser: Vec<u8, 32> = to_vec_cobs(data).unwrap();
112/// assert_eq!(ser.deref(), &[0x03, 0x04, 0x01, 0x03, 0x20, 0x30, 0x00]);
113///
114/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
115/// let ser: Vec<u8, 32> = to_vec_cobs(data).unwrap();
116/// assert_eq!(ser.deref(), &[0x02, 0x01, 0x03, 0x20, 0x30, 0x00]);
117/// ```
118#[cfg(feature = "heapless")]
119#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
120pub fn to_vec_cobs<T, const B: usize>(value: &T) -> Result<Vec<u8, B>>
121where
122    T: Serialize + ?Sized,
123{
124    serialize_with_flavor::<T, Cobs<HVec<B>>, Vec<u8, B>>(value, Cobs::try_new(HVec::default())?)
125}
126
127/// Serialize a `T` to a `heapless::Vec<u8>`, with the `Vec` containing
128/// data in a serialized format.
129///
130/// ## Example
131///
132/// ```rust
133/// use postcard::to_vec;
134/// use heapless::Vec;
135/// use core::ops::Deref;
136///
137/// let ser: Vec<u8, 32> = to_vec(&true).unwrap();
138/// assert_eq!(ser.deref(), &[0x01]);
139///
140/// let ser: Vec<u8, 32> = to_vec("Hi!").unwrap();
141/// assert_eq!(ser.deref(), &[0x03, b'H', b'i', b'!']);
142///
143/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
144/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
145/// let ser: Vec<u8, 32> = to_vec(data).unwrap();
146/// assert_eq!(ser.deref(), &[0x04, 0x01, 0x00, 0x20, 0x30]);
147///
148/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
149/// let ser: Vec<u8, 32> = to_vec(data).unwrap();
150/// assert_eq!(ser.deref(), &[0x01, 0x00, 0x20, 0x30]);
151/// ```
152#[cfg(feature = "heapless")]
153#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
154pub fn to_vec<T, const B: usize>(value: &T) -> Result<Vec<u8, B>>
155where
156    T: Serialize + ?Sized,
157{
158    serialize_with_flavor::<T, HVec<B>, Vec<u8, B>>(value, HVec::default())
159}
160
161/// Serialize a `T` to a `std::vec::Vec<u8>`.
162///
163/// ## Example
164///
165/// ```rust
166/// use postcard::to_stdvec;
167///
168/// let ser: Vec<u8> = to_stdvec(&true).unwrap();
169/// assert_eq!(ser.as_slice(), &[0x01]);
170///
171/// let ser: Vec<u8> = to_stdvec("Hi!").unwrap();
172/// assert_eq!(ser.as_slice(), &[0x03, b'H', b'i', b'!']);
173/// ```
174#[cfg(feature = "use-std")]
175#[cfg_attr(docsrs, doc(cfg(feature = "use-std")))]
176#[inline]
177pub fn to_stdvec<T>(value: &T) -> Result<std::vec::Vec<u8>>
178where
179    T: Serialize + ?Sized,
180{
181    to_allocvec(value)
182}
183
184/// Serialize and COBS encode a `T` to a `std::vec::Vec<u8>`.
185///
186/// The terminating sentinel `0x00` byte is included in the output.
187///
188/// ## Example
189///
190/// ```rust
191/// use postcard::to_stdvec_cobs;
192///
193/// let ser: Vec<u8> = to_stdvec_cobs(&true).unwrap();
194/// assert_eq!(ser.as_slice(), &[0x02, 0x01, 0x00]);
195///
196/// let ser: Vec<u8> = to_stdvec_cobs("Hi!").unwrap();
197/// assert_eq!(ser.as_slice(), &[0x05, 0x03, b'H', b'i', b'!', 0x00]);
198/// ```
199#[cfg(feature = "use-std")]
200#[cfg_attr(docsrs, doc(cfg(feature = "use-std")))]
201#[inline]
202pub fn to_stdvec_cobs<T>(value: &T) -> Result<std::vec::Vec<u8>>
203where
204    T: Serialize + ?Sized,
205{
206    to_allocvec_cobs(value)
207}
208
209/// Serialize a `T` to an `alloc::vec::Vec<u8>`.
210///
211/// ## Example
212///
213/// ```rust
214/// use postcard::to_allocvec;
215///
216/// let ser: Vec<u8> = to_allocvec(&true).unwrap();
217/// assert_eq!(ser.as_slice(), &[0x01]);
218///
219/// let ser: Vec<u8> = to_allocvec("Hi!").unwrap();
220/// assert_eq!(ser.as_slice(), &[0x03, b'H', b'i', b'!']);
221/// ```
222#[cfg(feature = "alloc")]
223#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
224pub fn to_allocvec<T>(value: &T) -> Result<alloc::vec::Vec<u8>>
225where
226    T: Serialize + ?Sized,
227{
228    serialize_with_flavor::<T, AllocVec, alloc::vec::Vec<u8>>(value, AllocVec::new())
229}
230
231/// Serialize and COBS encode a `T` to an `alloc::vec::Vec<u8>`.
232///
233/// The terminating sentinel `0x00` byte is included in the output.
234///
235/// ## Example
236///
237/// ```rust
238/// use postcard::to_allocvec_cobs;
239///
240/// let ser: Vec<u8> = to_allocvec_cobs(&true).unwrap();
241/// assert_eq!(ser.as_slice(), &[0x02, 0x01, 0x00]);
242///
243/// let ser: Vec<u8> = to_allocvec_cobs("Hi!").unwrap();
244/// assert_eq!(ser.as_slice(), &[0x05, 0x03, b'H', b'i', b'!', 0x00]);
245/// ```
246#[cfg(feature = "alloc")]
247#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
248pub fn to_allocvec_cobs<T>(value: &T) -> Result<alloc::vec::Vec<u8>>
249where
250    T: Serialize + ?Sized,
251{
252    serialize_with_flavor::<T, Cobs<AllocVec>, alloc::vec::Vec<u8>>(
253        value,
254        Cobs::try_new(AllocVec::new())?,
255    )
256}
257
258/// Serialize a `T` to a [`core::iter::Extend`],
259/// ## Example
260///
261/// ```rust
262/// use postcard::to_extend;
263/// let mut vec = Vec::new();
264///
265/// let ser = to_extend(&true, vec).unwrap();
266/// let vec = to_extend("Hi!", ser).unwrap();
267/// assert_eq!(&vec[0..5], &[0x01, 0x03, b'H', b'i', b'!']);
268/// ```
269pub fn to_extend<T, W>(value: &T, writer: W) -> Result<W>
270where
271    T: Serialize + ?Sized,
272    W: core::iter::Extend<u8>,
273{
274    serialize_with_flavor::<T, _, _>(value, flavors::ExtendFlavor::new(writer))
275}
276
277/// Serialize a `T` to an [`embedded_io Write`](crate::eio::Write),
278/// ## Example
279///
280/// ```rust
281/// use postcard::to_eio;
282/// let mut buf: [u8; 32] = [0; 32];
283/// let mut writer: &mut [u8] = &mut buf;
284///
285/// let ser = to_eio(&true, &mut writer).unwrap();
286/// to_eio("Hi!", ser).unwrap();
287/// assert_eq!(&buf[0..5], &[0x01, 0x03, b'H', b'i', b'!']);
288/// ```
289#[cfg(any(feature = "embedded-io-04", feature = "embedded-io-06"))]
290pub fn to_eio<T, W>(value: &T, writer: W) -> Result<W>
291where
292    T: Serialize + ?Sized,
293    W: crate::eio::Write,
294{
295    serialize_with_flavor::<T, _, _>(value, flavors::eio::WriteFlavor::new(writer))
296}
297
298/// Serialize a `T` to a [`std::io::Write`],
299/// ## Example
300///
301/// ```rust
302/// use postcard::to_io;
303/// let mut buf: [u8; 32] = [0; 32];
304/// let mut writer: &mut [u8] = &mut buf;
305///
306/// let ser = to_io(&true, &mut writer).unwrap();
307/// to_io("Hi!", ser).unwrap();
308/// assert_eq!(&buf[0..5], &[0x01, 0x03, b'H', b'i', b'!']);
309/// ```
310#[cfg(feature = "use-std")]
311pub fn to_io<T, W>(value: &T, writer: W) -> Result<W>
312where
313    T: Serialize + ?Sized,
314    W: std::io::Write,
315{
316    serialize_with_flavor::<T, _, _>(value, flavors::io::WriteFlavor::new(writer))
317}
318
319/// Conveniently serialize a `T` to the given slice, with the resulting slice containing
320/// data followed by a 32-bit CRC. The CRC bytes are included in the output buffer.
321///
322/// When successful, this function returns the slice containing the
323/// serialized and encoded message.
324///
325/// ## Example
326///
327/// ```rust
328/// use crc::{Crc, CRC_32_ISCSI};
329///
330/// let mut buf = [0; 9];
331///
332/// let data: &[u8] = &[0x01, 0x00, 0x20, 0x30];
333/// let crc = Crc::<u32>::new(&CRC_32_ISCSI);
334/// let used = postcard::to_slice_crc32(data, &mut buf, crc.digest()).unwrap();
335/// assert_eq!(used, &[0x04, 0x01, 0x00, 0x20, 0x30, 0x8E, 0xC8, 0x1A, 0x37]);
336/// ```
337///
338/// See the `ser_flavors::crc` module for the complete set of functions.
339#[cfg(feature = "use-crc")]
340#[cfg_attr(docsrs, doc(cfg(feature = "use-crc")))]
341#[inline]
342pub fn to_slice_crc32<'a, T>(
343    value: &T,
344    buf: &'a mut [u8],
345    digest: crc::Digest<'_, u32>,
346) -> Result<&'a mut [u8]>
347where
348    T: Serialize + ?Sized,
349{
350    flavors::crc::to_slice_u32(value, buf, digest)
351}
352
353/// Conveniently serialize a `T` to a `heapless::Vec<u8>`, with the `Vec` containing
354/// data followed by a 32-bit  CRC. The CRC bytes are included in the output `Vec`.
355///
356/// ## Example
357///
358/// ```rust
359/// use crc::{Crc, CRC_32_ISCSI};
360/// use heapless::Vec;
361/// use core::ops::Deref;
362///
363/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
364/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
365/// let crc = Crc::<u32>::new(&CRC_32_ISCSI);
366/// let ser: Vec<u8, 32> = postcard::to_vec_crc32(data, crc.digest()).unwrap();
367/// assert_eq!(ser.deref(), &[0x04, 0x01, 0x00, 0x20, 0x30, 0x8E, 0xC8, 0x1A, 0x37]);
368///
369/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
370/// let ser: Vec<u8, 32> = postcard::to_vec_crc32(data, crc.digest()).unwrap();
371/// assert_eq!(ser.deref(), &[0x01, 0x00, 0x20, 0x30, 0xCC, 0x4B, 0x4A, 0xDA]);
372/// ```
373///
374/// See the `ser_flavors::crc` module for the complete set of functions.
375#[cfg(all(feature = "use-crc", feature = "heapless"))]
376#[cfg_attr(docsrs, doc(cfg(all(feature = "use-crc", feature = "heapless"))))]
377#[inline]
378pub fn to_vec_crc32<T, const B: usize>(
379    value: &T,
380    digest: crc::Digest<'_, u32>,
381) -> Result<heapless::Vec<u8, B>>
382where
383    T: Serialize + ?Sized,
384{
385    flavors::crc::to_vec_u32(value, digest)
386}
387
388/// Conveniently serialize a `T` to a `heapless::Vec<u8>`, with the `Vec` containing
389/// data followed by a 32-bit  CRC. The CRC bytes are included in the output `Vec`.
390///
391/// ## Example
392///
393/// ```rust
394/// use crc::{Crc, CRC_32_ISCSI};
395/// use core::ops::Deref;
396///
397/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
398/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
399/// let crc = Crc::<u32>::new(&CRC_32_ISCSI);
400/// let ser: Vec<u8> = postcard::to_stdvec_crc32(data, crc.digest()).unwrap();
401/// assert_eq!(ser.deref(), &[0x04, 0x01, 0x00, 0x20, 0x30, 0x8E, 0xC8, 0x1A, 0x37]);
402///
403/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
404/// let ser: Vec<u8> = postcard::to_stdvec_crc32(data, crc.digest()).unwrap();
405/// assert_eq!(ser.deref(), &[0x01, 0x00, 0x20, 0x30, 0xCC, 0x4B, 0x4A, 0xDA]);
406/// ```
407///
408/// See the `ser_flavors::crc` module for the complete set of functions.
409#[cfg(all(feature = "use-crc", feature = "use-std"))]
410#[cfg_attr(docsrs, doc(cfg(all(feature = "use-crc", feature = "use-std"))))]
411#[inline]
412pub fn to_stdvec_crc32<T>(value: &T, digest: crc::Digest<'_, u32>) -> Result<std::vec::Vec<u8>>
413where
414    T: Serialize + ?Sized,
415{
416    flavors::crc::to_allocvec_u32(value, digest)
417}
418
419/// Conveniently serialize a `T` to a `heapless::Vec<u8>`, with the `Vec` containing
420/// data followed by a 32-bit  CRC. The CRC bytes are included in the output `Vec`.
421///
422/// ## Example
423///
424/// ```rust
425/// use crc::{Crc, CRC_32_ISCSI};
426/// use core::ops::Deref;
427///
428/// // NOTE: postcard handles `&[u8]` and `&[u8; N]` differently.
429/// let data: &[u8] = &[0x01u8, 0x00, 0x20, 0x30];
430/// let crc = Crc::<u32>::new(&CRC_32_ISCSI);
431/// let ser: Vec<u8> = postcard::to_allocvec_crc32(data, crc.digest()).unwrap();
432/// assert_eq!(ser.deref(), &[0x04, 0x01, 0x00, 0x20, 0x30, 0x8E, 0xC8, 0x1A, 0x37]);
433///
434/// let data: &[u8; 4] = &[0x01u8, 0x00, 0x20, 0x30];
435/// let ser: Vec<u8> = postcard::to_allocvec_crc32(data, crc.digest()).unwrap();
436/// assert_eq!(ser.deref(), &[0x01, 0x00, 0x20, 0x30, 0xCC, 0x4B, 0x4A, 0xDA]);
437/// ```
438///
439/// See the `ser_flavors::crc` module for the complete set of functions.
440#[cfg(all(feature = "use-crc", feature = "alloc"))]
441#[cfg_attr(docsrs, doc(cfg(all(feature = "use-crc", feature = "alloc"))))]
442#[inline]
443pub fn to_allocvec_crc32<T>(value: &T, digest: crc::Digest<'_, u32>) -> Result<alloc::vec::Vec<u8>>
444where
445    T: Serialize + ?Sized,
446{
447    flavors::crc::to_allocvec_u32(value, digest)
448}
449
450/// `serialize_with_flavor()` has three generic parameters, `T, F, O`.
451///
452/// * `T`: This is the type that is being serialized
453/// * `S`: This is the Storage that is used during serialization
454/// * `O`: This is the resulting storage type that is returned containing the serialized data
455///
456/// For more information about how Flavors work, please see the
457/// [`flavors` module documentation](./flavors/index.html).
458///
459/// ```rust
460/// use postcard::{
461///     serialize_with_flavor,
462///     ser_flavors::{Cobs, Slice},
463/// };
464///
465/// let mut buf = [0u8; 32];
466///
467/// let data: &[u8] = &[0x01, 0x00, 0x20, 0x30];
468/// let buffer = &mut [0u8; 32];
469/// let res = serialize_with_flavor::<[u8], Cobs<Slice>, &mut [u8]>(
470///     data,
471///     Cobs::try_new(Slice::new(buffer)).unwrap(),
472/// ).unwrap();
473///
474/// assert_eq!(res, &[0x03, 0x04, 0x01, 0x03, 0x20, 0x30, 0x00]);
475/// ```
476pub fn serialize_with_flavor<T, S, O>(value: &T, storage: S) -> Result<O>
477where
478    T: Serialize + ?Sized,
479    S: Flavor<Output = O>,
480{
481    let mut serializer = Serializer { output: storage };
482    value.serialize(&mut serializer)?;
483    serializer
484        .output
485        .finalize()
486        .map_err(|_| Error::SerializeBufferFull)
487}
488
489/// Compute the size of the postcard serialization of `T`.
490pub fn serialized_size<T>(value: &T) -> Result<usize>
491where
492    T: Serialize + ?Sized,
493{
494    serialize_with_flavor::<T, flavors::Size, usize>(value, flavors::Size::default())
495}
496
497#[cfg(feature = "heapless")]
498#[cfg(test)]
499mod test {
500    use super::*;
501    use crate::max_size::MaxSize;
502    use crate::varint::{varint_max, varint_usize};
503    use core::fmt::Write;
504    use core::ops::{Deref, DerefMut};
505    use heapless::{FnvIndexMap, String};
506    use serde::Deserialize;
507
508    #[test]
509    fn ser_u8() {
510        let output: Vec<u8, 1> = to_vec(&0x05u8).unwrap();
511        assert_eq!(&[5], output.deref());
512        assert!(output.len() == serialized_size(&0x05u8).unwrap());
513        assert!(output.len() <= Vec::<u8, 1>::POSTCARD_MAX_SIZE);
514    }
515
516    #[test]
517    fn ser_u16() {
518        const SZ: usize = varint_max::<u16>();
519        let output: Vec<u8, SZ> = to_vec(&0xA5C7u16).unwrap();
520        assert_eq!(&[0xC7, 0xCB, 0x02], output.deref());
521        assert!(output.len() == serialized_size(&0xA5C7u16).unwrap());
522        assert!(output.len() <= Vec::<u8, SZ>::POSTCARD_MAX_SIZE);
523    }
524
525    #[test]
526    fn ser_u32() {
527        const SZ: usize = varint_max::<u32>();
528        let output: Vec<u8, SZ> = to_vec(&0xCDAB3412u32).unwrap();
529        assert_eq!(&[0x92, 0xE8, 0xAC, 0xED, 0x0C], output.deref());
530        assert!(output.len() == serialized_size(&0xCDAB3412u32).unwrap());
531        assert!(output.len() <= Vec::<u8, SZ>::POSTCARD_MAX_SIZE);
532    }
533
534    #[test]
535    fn ser_u64() {
536        const SZ: usize = varint_max::<u64>();
537        let output: Vec<u8, SZ> = to_vec(&0x1234_5678_90AB_CDEFu64).unwrap();
538        assert_eq!(
539            &[0xEF, 0x9B, 0xAF, 0x85, 0x89, 0xCF, 0x95, 0x9A, 0x12],
540            output.deref()
541        );
542        assert!(output.len() == serialized_size(&0x1234_5678_90AB_CDEFu64).unwrap());
543        assert!(output.len() <= Vec::<u8, SZ>::POSTCARD_MAX_SIZE);
544    }
545
546    #[test]
547    fn ser_u128() {
548        const SZ: usize = varint_max::<u128>();
549        let output: Vec<u8, SZ> = to_vec(&0x1234_5678_90AB_CDEF_1234_5678_90AB_CDEFu128).unwrap();
550        assert_eq!(
551            &[
552                0xEF, 0x9B, 0xAF, 0x85, 0x89, 0xCF, 0x95, 0x9A, 0x92, 0xDE, 0xB7, 0xDE, 0x8A, 0x92,
553                0x9E, 0xAB, 0xB4, 0x24,
554            ],
555            output.deref()
556        );
557        assert!(
558            output.len()
559                == serialized_size(&0x1234_5678_90AB_CDEF_1234_5678_90AB_CDEFu128).unwrap()
560        );
561        assert!(output.len() <= Vec::<u8, SZ>::POSTCARD_MAX_SIZE);
562    }
563
564    #[derive(Serialize)]
565    struct BasicU8S {
566        st: u16,
567        ei: u8,
568        ote: u128,
569        sf: u64,
570        tt: u32,
571    }
572
573    impl MaxSize for BasicU8S {
574        const POSTCARD_MAX_SIZE: usize = {
575            u16::POSTCARD_MAX_SIZE
576                + u8::POSTCARD_MAX_SIZE
577                + u128::POSTCARD_MAX_SIZE
578                + u64::POSTCARD_MAX_SIZE
579                + u32::POSTCARD_MAX_SIZE
580        };
581    }
582
583    #[test]
584    fn ser_struct_unsigned() {
585        const SZ: usize = BasicU8S::POSTCARD_MAX_SIZE;
586        let input = BasicU8S {
587            st: 0xABCD,
588            ei: 0xFE,
589            ote: 0x1234_4321_ABCD_DCBA_1234_4321_ABCD_DCBA,
590            sf: 0x1234_4321_ABCD_DCBA,
591            tt: 0xACAC_ACAC,
592        };
593        let output: Vec<u8, SZ> = to_vec(&input).unwrap();
594
595        assert_eq!(
596            &[
597                0xCD, 0xD7, 0x02, 0xFE, 0xBA, 0xB9, 0xB7, 0xDE, 0x9A, 0xE4, 0x90, 0x9A, 0x92, 0xF4,
598                0xF2, 0xEE, 0xBC, 0xB5, 0xC8, 0xA1, 0xB4, 0x24, 0xBA, 0xB9, 0xB7, 0xDE, 0x9A, 0xE4,
599                0x90, 0x9A, 0x12, 0xAC, 0xD9, 0xB2, 0xE5, 0x0A
600            ],
601            output.deref()
602        );
603        assert!(output.len() == serialized_size(&input).unwrap());
604        assert!(output.len() <= BasicU8S::POSTCARD_MAX_SIZE);
605    }
606
607    #[test]
608    fn ser_byte_slice() {
609        let input: &[u8] = &[1u8, 2, 3, 4, 5, 6, 7, 8];
610        let output: Vec<u8, 9> = to_vec(input).unwrap();
611        assert_eq!(
612            &[0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
613            output.deref()
614        );
615        assert!(output.len() == serialized_size(&input).unwrap());
616
617        let mut input: Vec<u8, 1024> = Vec::new();
618        for i in 0..1024 {
619            input.push((i & 0xFF) as u8).unwrap();
620        }
621        let output: Vec<u8, 2048> = to_vec(input.deref()).unwrap();
622        assert_eq!(&[0x80, 0x08], &output.deref()[..2]);
623
624        assert_eq!(output.len(), 1026);
625        for (i, val) in output.deref()[2..].iter().enumerate() {
626            assert_eq!((i & 0xFF) as u8, *val);
627        }
628    }
629
630    #[test]
631    fn ser_str() {
632        let input: &str = "hello, postcard!";
633        let output: Vec<u8, 17> = to_vec(input).unwrap();
634        assert_eq!(0x10, output.deref()[0]);
635        assert_eq!(input.as_bytes(), &output.deref()[1..]);
636        assert!(output.len() == serialized_size(&input).unwrap());
637
638        let mut input: String<1024> = String::new();
639        for _ in 0..256 {
640            write!(&mut input, "abcd").unwrap();
641        }
642        let output: Vec<u8, 2048> = to_vec(input.deref()).unwrap();
643        assert_eq!(&[0x80, 0x08], &output.deref()[..2]);
644        assert!(String::<1024>::POSTCARD_MAX_SIZE <= output.len());
645
646        assert_eq!(output.len(), 1026);
647        for ch in output.deref()[2..].chunks(4) {
648            assert_eq!("abcd", core::str::from_utf8(ch).unwrap());
649        }
650    }
651
652    #[test]
653    fn usize_varint_encode() {
654        let mut buf = [0; varint_max::<usize>()];
655        let res = varint_usize(1, &mut buf);
656
657        assert_eq!(&[1], res);
658
659        let res = varint_usize(usize::MAX, &mut buf);
660
661        //
662        if varint_max::<usize>() == varint_max::<u32>() {
663            assert_eq!(&[0xFF, 0xFF, 0xFF, 0xFF, 0x0F], res);
664        } else if varint_max::<usize>() == varint_max::<u64>() {
665            assert_eq!(
666                &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01],
667                res
668            );
669        } else {
670            panic!("Update this test for 16/128 bit targets!");
671        }
672    }
673
674    #[allow(dead_code)]
675    #[derive(Serialize)]
676    enum BasicEnum {
677        Bib,
678        Bim,
679        Bap,
680    }
681
682    #[derive(Serialize)]
683    struct EnumStruct {
684        eight: u8,
685        sixt: u16,
686    }
687
688    #[derive(Serialize)]
689    enum DataEnum {
690        Bib(u16),
691        Bim(u64),
692        Bap(u8),
693        Kim(EnumStruct),
694        Chi { a: u8, b: u32 },
695        Sho(u16, u8),
696    }
697
698    #[test]
699    fn enums() {
700        let input = BasicEnum::Bim;
701        let output: Vec<u8, 1> = to_vec(&input).unwrap();
702        assert_eq!(&[0x01], output.deref());
703        assert!(output.len() == serialized_size(&input).unwrap());
704
705        let input = DataEnum::Bim(u64::MAX);
706        let output: Vec<u8, { 1 + varint_max::<u64>() }> = to_vec(&input).unwrap();
707        assert_eq!(
708            &[0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01],
709            output.deref()
710        );
711        assert!(output.len() == serialized_size(&input).unwrap());
712
713        let input = DataEnum::Bib(u16::MAX);
714        let output: Vec<u8, { 1 + varint_max::<u16>() }> = to_vec(&input).unwrap();
715        assert_eq!(&[0x00, 0xFF, 0xFF, 0x03], output.deref());
716        assert!(output.len() == serialized_size(&input).unwrap());
717
718        let input = DataEnum::Bap(u8::MAX);
719        let output: Vec<u8, 2> = to_vec(&input).unwrap();
720        assert_eq!(&[0x02, 0xFF], output.deref());
721        assert!(output.len() == serialized_size(&input).unwrap());
722
723        let input = DataEnum::Kim(EnumStruct {
724            eight: 0xF0,
725            sixt: 0xACAC,
726        });
727        let output: Vec<u8, 8> = to_vec(&input).unwrap();
728        assert_eq!(&[0x03, 0xF0, 0xAC, 0xD9, 0x02], output.deref());
729        assert!(output.len() == serialized_size(&input).unwrap());
730
731        let input = DataEnum::Chi {
732            a: 0x0F,
733            b: 0xC7C7C7C7,
734        };
735        let output: Vec<u8, 8> = to_vec(&input).unwrap();
736        assert_eq!(&[0x04, 0x0F, 0xC7, 0x8F, 0x9F, 0xBE, 0x0C], output.deref());
737        assert!(output.len() == serialized_size(&input).unwrap());
738
739        let input = DataEnum::Sho(0x6969, 0x07);
740        let output: Vec<u8, 8> = to_vec(&input).unwrap();
741        assert_eq!(&[0x05, 0xE9, 0xD2, 0x01, 0x07], output.deref());
742        assert!(output.len() == serialized_size(&input).unwrap());
743    }
744
745    #[test]
746    fn tuples() {
747        let input = (1u8, 10u32, "Hello!");
748        let output: Vec<u8, 128> = to_vec(&input).unwrap();
749        assert_eq!(
750            &[1u8, 0x0A, 0x06, b'H', b'e', b'l', b'l', b'o', b'!'],
751            output.deref()
752        );
753        assert!(output.len() == serialized_size(&input).unwrap());
754    }
755
756    #[test]
757    fn bytes() {
758        let x: &[u8; 32] = &[0u8; 32];
759        let output: Vec<u8, 128> = to_vec(x).unwrap();
760        assert_eq!(output.len(), 32);
761        assert!(output.len() == serialized_size(&x).unwrap());
762        assert!(<[u8; 32] as MaxSize>::POSTCARD_MAX_SIZE <= output.len());
763
764        let x: &[u8] = &[0u8; 32];
765        let output: Vec<u8, 128> = to_vec(x).unwrap();
766        assert_eq!(output.len(), 33);
767        assert!(output.len() == serialized_size(&x).unwrap());
768    }
769
770    #[derive(Serialize)]
771    pub struct NewTypeStruct(u32);
772
773    #[derive(Serialize)]
774    pub struct TupleStruct((u8, u16));
775
776    #[test]
777    fn structs() {
778        let input = NewTypeStruct(5);
779        let output: Vec<u8, 1> = to_vec(&input).unwrap();
780        assert_eq!(&[0x05], output.deref());
781        assert!(output.len() == serialized_size(&input).unwrap());
782
783        let input = TupleStruct((0xA0, 0x1234));
784        let output: Vec<u8, 3> = to_vec(&input).unwrap();
785        assert_eq!(&[0xA0, 0xB4, 0x24], output.deref());
786        assert!(output.len() == serialized_size(&input).unwrap());
787    }
788
789    #[derive(Serialize, Deserialize, Eq, PartialEq, Debug)]
790    struct RefStruct<'a> {
791        bytes: &'a [u8],
792        str_s: &'a str,
793    }
794
795    #[test]
796    fn ref_struct() {
797        let message = "hElLo";
798        let bytes = [0x01, 0x10, 0x02, 0x20];
799        let input = RefStruct {
800            bytes: &bytes,
801            str_s: message,
802        };
803        let output: Vec<u8, 11> = to_vec(&input).unwrap();
804
805        assert_eq!(
806            &[0x04, 0x01, 0x10, 0x02, 0x20, 0x05, b'h', b'E', b'l', b'L', b'o',],
807            output.deref()
808        );
809        assert!(output.len() == serialized_size(&input).unwrap());
810    }
811
812    #[test]
813    fn unit() {
814        let output: Vec<u8, 1> = to_vec(&()).unwrap();
815        assert_eq!(output.len(), 0);
816        assert!(output.len() == serialized_size(&()).unwrap());
817    }
818
819    #[test]
820    fn heapless_data() {
821        let mut input: Vec<u8, 4> = Vec::new();
822        input.extend_from_slice(&[0x01, 0x02, 0x03, 0x04]).unwrap();
823        let output: Vec<u8, 5> = to_vec(&input).unwrap();
824        assert_eq!(&[0x04, 0x01, 0x02, 0x03, 0x04], output.deref());
825        assert!(output.len() == serialized_size(&input).unwrap());
826
827        let mut input: String<8> = String::new();
828        write!(&mut input, "helLO!").unwrap();
829        let output: Vec<u8, 7> = to_vec(&input).unwrap();
830        assert_eq!(&[0x06, b'h', b'e', b'l', b'L', b'O', b'!'], output.deref());
831        assert!(output.len() == serialized_size(&input).unwrap());
832
833        let mut input: FnvIndexMap<u8, u8, 4> = FnvIndexMap::new();
834        input.insert(0x01, 0x05).unwrap();
835        input.insert(0x02, 0x06).unwrap();
836        input.insert(0x03, 0x07).unwrap();
837        input.insert(0x04, 0x08).unwrap();
838        let output: Vec<u8, 100> = to_vec(&input).unwrap();
839        assert_eq!(
840            &[0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07, 0x04, 0x08],
841            output.deref()
842        );
843        assert!(output.len() == serialized_size(&input).unwrap());
844    }
845
846    #[test]
847    fn cobs_test() {
848        let message = "hElLo";
849        let bytes = [0x01, 0x00, 0x02, 0x20];
850        let input = RefStruct {
851            bytes: &bytes,
852            str_s: message,
853        };
854
855        let mut output: Vec<u8, 13> = to_vec_cobs(&input).unwrap();
856
857        let sz = cobs::decode_in_place(output.deref_mut()).unwrap();
858
859        let x = crate::from_bytes::<RefStruct<'_>>(&output.deref_mut()[..sz]).unwrap();
860
861        assert_eq!(input, x);
862    }
863}