musli/
compat.rs

1//! Wrapper types for tweaking how something is encoded.
2//!
3//! Note that most types in this module have an attribute equivalent:
4//! * [`Bytes`] corresponds to using `#[musli(bytes)]` on a field.
5//! * [`Packed`] corresponds to using `#[musli(packed)]` on a field.
6
7use crate::de::{Decode, DecodeBytes, DecodePacked, Decoder};
8use crate::en::{Encode, EncodeBytes, EncodePacked, Encoder};
9use crate::hint::SequenceHint;
10use crate::mode::{Binary, Text};
11
12/// Ensures that the given value `T` is encoded as a sequence.
13///
14/// This exists as a simple shim for certain types, to ensure they're encoded as
15/// a sequence, such as `Sequence<()>`.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[repr(transparent)]
18pub struct Sequence<T>(pub T);
19
20impl<T> Sequence<T> {
21    /// Construct a new sequence wrapper.
22    pub const fn new(value: T) -> Self {
23        Self(value)
24    }
25}
26
27impl<M> Encode<M> for Sequence<()> {
28    #[inline]
29    fn encode<E>(&self, _: &E::Cx, encoder: E) -> Result<E::Ok, E::Error>
30    where
31        E: Encoder<Mode = M>,
32    {
33        static HINT: SequenceHint = SequenceHint::with_size(0);
34
35        encoder.encode_sequence_fn(&HINT, |_| Ok(()))
36    }
37}
38
39impl<'de, M> Decode<'de, M> for Sequence<()> {
40    fn decode<D>(_: &D::Cx, decoder: D) -> Result<Self, D::Error>
41    where
42        D: Decoder<'de>,
43    {
44        decoder.decode_sequence(|_| Ok(Self(())))
45    }
46}
47
48/// Treat `T` as if its bytes.
49///
50/// This corresponds to the "Bytes" type in the [data model of Müsli] and is the
51/// equivalent of using [`#[musli(bytes)]`][bytes] on a field.
52///
53/// This is only implemented for type where the default behavior is not to pack
54/// the value already, this applies to types which implements [`EncodeBytes`]
55/// and [`DecodeBytes`].
56///
57/// [`Vec`]: alloc::vec::Vec
58/// [`VecDeque`]: alloc::collections::VecDeque
59/// [bytes]: crate::help::derives
60/// [data model of Müsli]: crate::help::data_model
61///
62/// # Examples
63///
64/// ```
65/// use musli::{Decode, Decoder};
66/// use musli::compat::Bytes;
67///
68/// struct Struct {
69///     field: Vec<u8>,
70/// }
71///
72/// impl<'de, M> Decode<'de, M> for Struct
73/// where
74///     Bytes<Vec<u8>>: Decode<'de, M>
75/// {
76///     fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
77///     where
78///         D: Decoder<'de, Mode = M>,
79///     {
80///         let Bytes(field) = Decode::decode(cx, decoder)?;
81///
82///         Ok(Struct {
83///             field,
84///         })
85///     }
86/// }
87/// ```
88#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
89#[musli(crate, transparent)]
90#[musli(mode = Binary, bound = {T: EncodeBytes<Binary>}, decode_bound = {T: DecodeBytes<'de, Binary>})]
91#[musli(mode = Text, bound = {T: EncodeBytes<Text>}, decode_bound = {T: DecodeBytes<'de, Text>})]
92#[repr(transparent)]
93pub struct Bytes<T>(#[musli(bytes)] pub T);
94
95impl<T> AsRef<[u8]> for Bytes<T>
96where
97    T: AsRef<[u8]>,
98{
99    #[inline]
100    fn as_ref(&self) -> &[u8] {
101        self.0.as_ref()
102    }
103}
104
105impl<T> AsMut<[u8]> for Bytes<T>
106where
107    T: AsMut<[u8]>,
108{
109    #[inline]
110    fn as_mut(&mut self) -> &mut [u8] {
111        self.0.as_mut()
112    }
113}
114
115/// Treat `T` as if its packed.
116///
117/// This corresponds to the "Bytes" type in the [data model of Müsli]. It
118/// encodes any [`Encode`] / [`Decode`] type "on after another" and is the
119/// equivalent of using [`#[musli(packed)]`][packed] on a field.
120///
121/// This is only implemented for type where the default behavior is not to pack
122/// the value already, this applies to types which implements [`EncodePacked`]
123/// and [`DecodePacked`].
124///
125/// [packed]: crate::help::derives
126///
127/// # Examples
128///
129/// ```
130/// use musli::{Decode, Decoder};
131/// use musli::compat::Packed;
132///
133/// struct Struct {
134///     field: u8,
135///     field2: u32,
136/// }
137///
138/// impl<'de, M> Decode<'de, M> for Struct
139/// where
140///     Packed<(u8, u32)>: Decode<'de, M>
141/// {
142///     fn decode<D>(cx: &D::Cx, decoder: D) -> Result<Self, D::Error>
143///     where
144///         D: Decoder<'de, Mode = M>,
145///     {
146///         let Packed((field, field2)) = Decode::decode(cx, decoder)?;
147///
148///         Ok(Struct {
149///             field,
150///             field2,
151///         })
152///     }
153/// }
154/// ```
155#[derive(Encode, Decode)]
156#[musli(crate, transparent)]
157#[musli(mode = Binary, bound = {T: EncodePacked<Binary>}, decode_bound = {T: DecodePacked<'de, Binary>})]
158#[musli(mode = Text, bound = {T: EncodePacked<Text>}, decode_bound = {T: DecodePacked<'de, Text>})]
159#[repr(transparent)]
160pub struct Packed<T>(#[musli(packed)] pub T);