musli/storage/encoding.rs
1//! Module that defines [`Encoding`] whith allows for customization of the
2//! encoding format, and the [`DEFAULT`] encoding configuration.
3
4use core::marker;
5
6use crate::mode::Binary;
7use crate::options;
8use crate::{IntoReader, Options};
9
10use super::de::StorageDecoder;
11use super::en::StorageEncoder;
12use super::error::Error;
13
14/// Default options to use with [`Encoding`].
15pub const OPTIONS: Options = options::new().build();
16
17/// The default configuration.
18///
19/// Uses variable-encoded numerical fields and variable-encoded prefix lengths.
20///
21/// The variable length encoding uses [`zigzag`] with [`variable length`]
22/// encoding for numbers.
23///
24/// [`zigzag`]: https://en.wikipedia.org/wiki/Variable-length_quantity#Zigzag_encoding
25/// [`variable length`]: https://en.wikipedia.org/wiki/Variable-length_quantity
26pub const DEFAULT: Encoding = Encoding::new();
27
28crate::macros::bare_encoding!(Binary, DEFAULT, storage, IntoReader);
29
30/// Setting up encoding with parameters.
31pub struct Encoding<const OPT: Options = OPTIONS, M = Binary>
32where
33 M: 'static,
34{
35 _marker: marker::PhantomData<M>,
36}
37
38impl Default for Encoding<OPTIONS, Binary> {
39 #[inline]
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45impl Encoding<OPTIONS, Binary> {
46 /// Construct a new [`Encoding`] instance which uses [`OPTIONS`].
47 ///
48 /// You can modify this behavior by using a custom [`Options`] instance:
49 ///
50 /// ```
51 /// use musli::{Encode, Decode};
52 /// use musli::options::{self, Options, Integer};
53 /// use musli::storage::Encoding;
54 /// # use musli::storage::Error;
55 ///
56 /// const OPTIONS: Options = options::new().with_integer(Integer::Fixed).build();
57 /// const CONFIG: Encoding<OPTIONS> = Encoding::new().with_options();
58 ///
59 /// #[derive(Debug, PartialEq, Encode, Decode)]
60 /// struct Person<'a> {
61 /// name: &'a str,
62 /// age: u32,
63 /// }
64 ///
65 /// let mut out = Vec::new();
66 ///
67 /// let expected = Person {
68 /// name: "Aristotle",
69 /// age: 61,
70 /// };
71 ///
72 /// CONFIG.encode(&mut out, &expected)?;
73 /// let actual = CONFIG.decode(&out[..])?;
74 ///
75 /// assert_eq!(expected, actual);
76 /// # Ok::<_, Error>(())
77 /// ```
78 pub const fn new() -> Self {
79 Encoding {
80 _marker: marker::PhantomData,
81 }
82 }
83}
84
85impl<const OPT: Options, M> Encoding<OPT, M>
86where
87 M: 'static,
88{
89 /// Change the mode of the encoding.
90 ///
91 /// # Examples
92 ///
93 /// ```rust
94 /// use musli::storage::{OPTIONS, Encoding};
95 ///
96 /// enum Custom {}
97 ///
98 /// const CONFIG: Encoding<OPTIONS, Custom> = Encoding::new().with_mode();
99 /// ```
100 pub const fn with_mode<T>(self) -> Encoding<OPT, T> {
101 Encoding {
102 _marker: marker::PhantomData,
103 }
104 }
105
106 /// Change the options of the encoding.
107 ///
108 /// # Examples
109 ///
110 /// ```
111 /// use musli::options::{self, Options, Integer};
112 /// use musli::storage::Encoding;
113 ///
114 /// const OPTIONS: Options = options::new().with_integer(Integer::Fixed).build();
115 /// const CONFIG: Encoding<OPTIONS> = Encoding::new().with_options();
116 /// ```
117 pub const fn with_options<const U: Options>(self) -> Encoding<U, M> {
118 Encoding {
119 _marker: marker::PhantomData,
120 }
121 }
122
123 crate::macros::encoding_impls!(
124 M,
125 storage,
126 StorageEncoder::<_, OPT, _>::new,
127 StorageDecoder::<_, OPT, _>::new,
128 IntoReader::into_reader,
129 );
130}
131
132impl<const OPT: Options, M> Clone for Encoding<OPT, M> {
133 #[inline]
134 fn clone(&self) -> Self {
135 *self
136 }
137}
138
139impl<const OPT: Options, M> Copy for Encoding<OPT, M> {}