musli_descriptive/encoding.rs
1//! Module that defines [`Encoding`] whith allows for customization of the
2//! encoding format, and the [`DEFAULT`] encoding configuration.
3
4#[cfg(feature = "alloc")]
5use alloc::vec::Vec;
6use core::marker;
7#[cfg(feature = "std")]
8use std::io;
9
10use musli::de::Decode;
11use musli::en::Encode;
12use musli::mode::Binary;
13use musli::Context;
14use musli_utils::options;
15use musli_utils::{FixedBytes, Options, Reader, Writer};
16
17use crate::de::SelfDecoder;
18use crate::en::SelfEncoder;
19use crate::error::Error;
20
21/// The default flavor used by the [`DEFAULT`] configuration.
22pub const OPTIONS: options::Options = options::new().build();
23
24/// The default configuration.
25///
26/// Uses variable-encoded numerical fields and variable-encoded prefix lengths.
27///
28/// The variable length encoding uses [`zigzag`] with [`continuation`] encoding
29/// for numbers.
30///
31/// [`zigzag`]: musli_utils::int::zigzag
32/// [`continuation`]: musli_utils::int::continuation
33pub const DEFAULT: Encoding = Encoding::new();
34
35/// Encode the given value to the given [`Writer`] using the [`DEFAULT`]
36/// configuration.
37#[inline]
38pub fn encode<W, T>(writer: W, value: &T) -> Result<(), Error>
39where
40 W: Writer,
41 T: ?Sized + Encode<Binary>,
42{
43 DEFAULT.encode(writer, value)
44}
45
46/// Encode the given value to the given [Write][io::Write] using the [`DEFAULT`]
47/// configuration.
48#[cfg(feature = "std")]
49#[inline]
50pub fn to_writer<W, T>(writer: W, value: &T) -> Result<(), Error>
51where
52 W: io::Write,
53 T: ?Sized + Encode<Binary>,
54{
55 DEFAULT.to_writer(writer, value)
56}
57
58/// Encode the given value to a [Vec] using the [`DEFAULT`] configuration.
59#[cfg(feature = "alloc")]
60#[inline]
61pub fn to_vec<T>(value: &T) -> Result<Vec<u8>, Error>
62where
63 T: ?Sized + Encode<Binary>,
64{
65 DEFAULT.to_vec(value)
66}
67
68/// Encode the given value to a fixed-size bytes using the [`DEFAULT`]
69/// configuration.
70#[inline]
71pub fn to_fixed_bytes<const N: usize, T>(value: &T) -> Result<FixedBytes<N>, Error>
72where
73 T: ?Sized + Encode<Binary>,
74{
75 DEFAULT.to_fixed_bytes::<N, _>(value)
76}
77
78/// Decode the given type `T` from the given [`Reader`] using the [`DEFAULT`]
79/// configuration.
80#[inline]
81pub fn decode<'de, R, T>(reader: R) -> Result<T, Error>
82where
83 R: Reader<'de>,
84 T: Decode<'de, Binary>,
85{
86 DEFAULT.decode(reader)
87}
88
89/// Decode the given type `T` from the given slice using the [`DEFAULT`]
90/// configuration.
91#[inline]
92pub fn from_slice<'de, T>(bytes: &'de [u8]) -> Result<T, Error>
93where
94 T: Decode<'de, Binary>,
95{
96 DEFAULT.from_slice(bytes)
97}
98
99/// Setting up encoding with parameters.
100pub struct Encoding<const OPT: Options = OPTIONS, M = Binary> {
101 _marker: marker::PhantomData<M>,
102}
103
104impl Encoding<OPTIONS, Binary> {
105 /// Construct a new [`Encoding`] instance.
106 ///
107 /// ```
108 /// use musli_descriptive::{Encoding};
109 /// use musli::{Encode, Decode};
110 ///
111 /// const CONFIG: Encoding = Encoding::new();
112 ///
113 /// #[derive(Debug, PartialEq, Encode, Decode)]
114 /// struct Struct<'a> {
115 /// name: &'a str,
116 /// age: u32,
117 /// }
118 ///
119 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
120 /// let mut out = Vec::new();
121 ///
122 /// let expected = Struct {
123 /// name: "Aristotle",
124 /// age: 61,
125 /// };
126 ///
127 /// CONFIG.encode(&mut out, &expected)?;
128 /// let actual = CONFIG.decode(&out[..])?;
129 ///
130 /// assert_eq!(expected, actual);
131 /// # Ok(()) }
132 /// ```
133 pub const fn new() -> Self {
134 Encoding {
135 _marker: marker::PhantomData,
136 }
137 }
138}
139
140impl<const OPT: Options, M> Encoding<OPT, M> {
141 /// Change the mode of the encoding.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use musli_descriptive::{OPTIONS, Encoding};
147 ///
148 /// enum Custom {}
149 ///
150 /// const CONFIG: Encoding<OPTIONS, Custom> = Encoding::new().with_mode();
151 /// ```
152 pub const fn with_mode<T>(self) -> Encoding<OPT, T> {
153 Encoding {
154 _marker: marker::PhantomData,
155 }
156 }
157
158 /// Change the options of the encoding.
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use musli_utils::options::{self, Options, Integer};
164 /// use musli_descriptive::Encoding;
165 ///
166 /// const OPTIONS: Options = options::new().with_integer(Integer::Fixed).build();
167 /// const CONFIG: Encoding<OPTIONS> = Encoding::new().with_options();
168 /// ```
169 pub const fn with_options<const U: Options>(self) -> Encoding<U, M> {
170 Encoding {
171 _marker: marker::PhantomData,
172 }
173 }
174
175 musli_utils::encoding_impls!(
176 M,
177 SelfEncoder::<_, OPT, _>::new,
178 SelfDecoder::<_, OPT, _>::new
179 );
180 musli_utils::encoding_from_slice_impls!(M);
181}
182
183impl<const OPT: Options, M> Clone for Encoding<OPT, M> {
184 #[inline]
185 fn clone(&self) -> Self {
186 *self
187 }
188}
189
190impl<const OPT: Options, M> Copy for Encoding<OPT, M> {}