Skip to main content

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