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);