facet_msgpack/
lib.rs

1//! MsgPack binary format for facet.
2//!
3//! This crate provides serialization and deserialization for the MessagePack binary format.
4//!
5//! # Serialization
6//!
7//! ```
8//! use facet::Facet;
9//! use facet_msgpack::to_vec;
10//!
11//! #[derive(Facet)]
12//! struct Point { x: i32, y: i32 }
13//!
14//! let point = Point { x: 10, y: 20 };
15//! let bytes = to_vec(&point).unwrap();
16//! ```
17//!
18//! # Deserialization
19//!
20//! There are two deserialization functions:
21//!
22//! - [`from_slice`]: Deserializes into owned types (`T: Facet<'static>`)
23//! - [`from_slice_borrowed`]: Deserializes with zero-copy borrowing from the input buffer
24//!
25//! ```
26//! use facet::Facet;
27//! use facet_msgpack::from_slice;
28//!
29//! #[derive(Facet, Debug, PartialEq)]
30//! struct Point { x: i32, y: i32 }
31//!
32//! // MsgPack encoding of {"x": 10, "y": 20}
33//! let bytes = &[0x82, 0xa1, b'x', 0x0a, 0xa1, b'y', 0x14];
34//! let point: Point = from_slice(bytes).unwrap();
35//! assert_eq!(point.x, 10);
36//! assert_eq!(point.y, 20);
37//! ```
38//!
39//! Both functions use Tier-2 JIT for compatible types (when the `jit` feature is enabled),
40//! with automatic fallback to Tier-0 reflection for all other types.
41
42#![cfg_attr(not(feature = "jit"), forbid(unsafe_code))]
43
44extern crate alloc;
45
46mod error;
47mod parser;
48mod serializer;
49
50#[cfg(feature = "jit")]
51pub mod jit;
52
53#[cfg(feature = "axum")]
54mod axum;
55
56pub use error::MsgPackError;
57
58#[cfg(feature = "axum")]
59pub use axum::{MsgPack, MsgPackRejection, MsgPackSerializeRejection};
60#[cfg(feature = "jit")]
61pub use jit::MsgPackJitFormat;
62pub use parser::MsgPackParser;
63pub use serializer::{MsgPackSerializeError, MsgPackSerializer, to_vec, to_writer};
64
65// Re-export DeserializeError for convenience
66pub use facet_format::DeserializeError;
67
68/// Deserialize a value from MsgPack bytes into an owned type.
69///
70/// This is the recommended default for most use cases. The input does not need
71/// to outlive the result, making it suitable for deserializing from temporary
72/// buffers (e.g., HTTP request bodies).
73///
74/// Types containing `&str` or `&[u8]` fields cannot be deserialized with this
75/// function; use `String`/`Vec<u8>` or `Cow<str>`/`Cow<[u8]>` instead. For
76/// zero-copy deserialization into borrowed types, use [`from_slice_borrowed`].
77///
78/// # Example
79///
80/// ```
81/// use facet::Facet;
82/// use facet_msgpack::from_slice;
83///
84/// #[derive(Facet, Debug, PartialEq)]
85/// struct Point {
86///     x: i32,
87///     y: i32,
88/// }
89///
90/// // MsgPack encoding of {"x": 10, "y": 20}
91/// let bytes = &[0x82, 0xa1, b'x', 0x0a, 0xa1, b'y', 0x14];
92/// let point: Point = from_slice(bytes).unwrap();
93/// assert_eq!(point.x, 10);
94/// assert_eq!(point.y, 20);
95/// ```
96pub fn from_slice<T>(input: &[u8]) -> Result<T, DeserializeError<MsgPackError>>
97where
98    T: facet_core::Facet<'static>,
99{
100    use facet_format::FormatDeserializer;
101    let parser = MsgPackParser::new(input);
102    let mut de = FormatDeserializer::new_owned(parser);
103    de.deserialize()
104}
105
106/// Deserialize a value from MsgPack bytes, allowing zero-copy borrowing.
107///
108/// This variant requires the input to outlive the result (`'input: 'facet`),
109/// enabling zero-copy deserialization of byte slices as `&[u8]` or `Cow<[u8]>`.
110///
111/// Use this when you need maximum performance and can guarantee the input
112/// buffer outlives the deserialized value. For most use cases, prefer
113/// [`from_slice`] which doesn't have lifetime requirements.
114///
115/// # Example
116///
117/// ```
118/// use facet::Facet;
119/// use facet_msgpack::from_slice_borrowed;
120///
121/// #[derive(Facet, Debug, PartialEq)]
122/// struct Message<'a> {
123///     id: u32,
124///     data: &'a [u8],
125/// }
126///
127/// // MsgPack encoding of {"id": 1, "data": <bin8 with 3 bytes>}
128/// let bytes = &[0x82, 0xa2, b'i', b'd', 0x01, 0xa4, b'd', b'a', b't', b'a', 0xc4, 0x03, 0xAB, 0xCD, 0xEF];
129/// let msg: Message = from_slice_borrowed(bytes).unwrap();
130/// assert_eq!(msg.id, 1);
131/// assert_eq!(msg.data, &[0xAB, 0xCD, 0xEF]);
132/// ```
133pub fn from_slice_borrowed<'input, 'facet, T>(
134    input: &'input [u8],
135) -> Result<T, DeserializeError<MsgPackError>>
136where
137    T: facet_core::Facet<'facet>,
138    'input: 'facet,
139{
140    use facet_format::FormatDeserializer;
141    let parser = MsgPackParser::new(input);
142    let mut de = FormatDeserializer::new(parser);
143    de.deserialize()
144}