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::mode::{Binary, Text};
10use crate::Allocator;
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    #[inline]
23    pub const fn new(value: T) -> Self {
24        Self(value)
25    }
26}
27
28impl<M> Encode<M> for Sequence<()> {
29    type Encode = Self;
30
31    const IS_BITWISE_ENCODE: bool = true;
32
33    #[inline]
34    fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
35    where
36        E: Encoder<Mode = M>,
37    {
38        encoder.encode_sequence_fn(0, |_| Ok(()))
39    }
40
41    #[inline]
42    fn as_encode(&self) -> &Self::Encode {
43        self
44    }
45}
46
47impl<'de, M, A> Decode<'de, M, A> for Sequence<()>
48where
49    A: Allocator,
50{
51    const IS_BITWISE_DECODE: bool = true;
52
53    #[inline]
54    fn decode<D>(decoder: D) -> Result<Self, D::Error>
55    where
56        D: Decoder<'de, Allocator = A>,
57    {
58        decoder.decode_sequence(|_| Ok(Self(())))
59    }
60}
61
62/// Treat `T` as if its bytes.
63///
64/// This corresponds to the "Bytes" type in the [data model of Müsli] and is the
65/// equivalent of using [`#[musli(bytes)]`][bytes] on a field.
66///
67/// This is only implemented for type where the default behavior is not to pack
68/// the value already, this applies to types which implements [`EncodeBytes`]
69/// and [`DecodeBytes`].
70///
71/// [`Vec`]: rust_alloc::vec::Vec
72/// [`VecDeque`]: rust_alloc::collections::VecDeque
73/// [bytes]: crate::_help::derives
74/// [data model of Müsli]: crate::_help::data_model
75///
76/// # Examples
77///
78/// ```
79/// use musli::{Allocator, Decode, Decoder};
80/// use musli::compat::Bytes;
81///
82/// struct Struct {
83///     field: Vec<u8>,
84/// }
85///
86/// impl<'de, M, A> Decode<'de, M, A> for Struct
87/// where
88///     A: Allocator,
89///     Bytes<Vec<u8>>: Decode<'de, M, A>
90/// {
91///     #[inline]
92///     fn decode<D>(decoder: D) -> Result<Self, D::Error>
93///     where
94///         D: Decoder<'de, Mode = M, Allocator = A>,
95///     {
96///         let Bytes(field) = decoder.decode()?;
97///
98///         Ok(Struct {
99///             field,
100///         })
101///     }
102/// }
103/// ```
104#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
105#[musli(crate, transparent)]
106#[musli(Binary, bound = {T: EncodeBytes<Binary>}, decode_bound<'de, A> = {T: DecodeBytes<'de, Binary, A>})]
107#[musli(Text, bound = {T: EncodeBytes<Text>}, decode_bound<'de, A> = {T: DecodeBytes<'de, Text, A>})]
108#[repr(transparent)]
109pub struct Bytes<T>(#[musli(bytes)] pub T);
110
111impl<T> AsRef<[u8]> for Bytes<T>
112where
113    T: AsRef<[u8]>,
114{
115    #[inline]
116    fn as_ref(&self) -> &[u8] {
117        self.0.as_ref()
118    }
119}
120
121impl<T> AsMut<[u8]> for Bytes<T>
122where
123    T: AsMut<[u8]>,
124{
125    #[inline]
126    fn as_mut(&mut self) -> &mut [u8] {
127        self.0.as_mut()
128    }
129}
130
131/// Treat `T` as if its packed.
132///
133/// This corresponds to the "Bytes" type in the [data model of Müsli]. It
134/// encodes any [`Encode`] / [`Decode`] type "on after another" and is the
135/// equivalent of using [`#[musli(packed)]`][packed] on a field.
136///
137/// This is only implemented for type where the default behavior is not to pack
138/// the value already, this applies to types which implements [`EncodePacked`]
139/// and [`DecodePacked`].
140///
141/// [packed]: crate::_help::derives
142///
143/// # Examples
144///
145/// ```
146/// use musli::{Allocator, Decode, Decoder};
147/// use musli::compat::Packed;
148///
149/// struct Struct {
150///     field: u8,
151///     field2: u32,
152/// }
153///
154/// impl<'de, M, A> Decode<'de, M, A> for Struct
155/// where
156///     A: Allocator,
157///     Packed<(u8, u32)>: Decode<'de, M, A>
158/// {
159///     #[inline]
160///     fn decode<D>(decoder: D) -> Result<Self, D::Error>
161///     where
162///         D: Decoder<'de, Mode = M, Allocator = A>,
163///     {
164///         let Packed((field, field2)) = decoder.decode()?;
165///
166///         Ok(Struct {
167///             field,
168///             field2,
169///         })
170///     }
171/// }
172/// ```
173#[derive(Encode, Decode)]
174#[musli(crate, transparent)]
175#[musli(Binary, bound = {T: EncodePacked<Binary>}, decode_bound<'de, A> = {T: DecodePacked<'de, Binary, A>})]
176#[musli(Text, bound = {T: EncodePacked<Text>}, decode_bound<'de, A> = {T: DecodePacked<'de, Text, A>})]
177#[repr(transparent)]
178pub struct Packed<T>(#[musli(packed)] pub T);