Coverage Report

Created: 2026-03-23 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rmp-serde-1.3.0/src/config.rs
Line
Count
Source
1
//! Change MessagePack behavior with configuration wrappers.
2
3
/// Represents configuration that dicatates what the serializer does.
4
///
5
/// Implemented as an empty trait depending on a hidden trait in order to allow changing the
6
/// methods of this trait without breaking backwards compatibility.
7
pub trait SerializerConfig: sealed::SerializerConfig {}
8
9
impl<T: sealed::SerializerConfig> SerializerConfig for T {}
10
11
pub(crate) mod sealed {
12
    use crate::config::BytesMode;
13
14
    /// This is the inner trait - the real `SerializerConfig`.
15
    ///
16
    /// This hack disallows external implementations and usage of `SerializerConfig` and thus
17
    /// allows us to change `SerializerConfig` methods freely without breaking backwards compatibility.
18
    pub trait SerializerConfig: Copy {
19
        /// Determines the value of `Serializer::is_human_readable` and
20
        /// `Deserializer::is_human_readable`.
21
        fn is_human_readable(&self) -> bool;
22
23
        /// String struct fields
24
        fn is_named(&self) -> bool;
25
        fn bytes(&self) -> BytesMode;
26
    }
27
}
28
29
#[derive(Copy, Clone, Debug)]
30
pub(crate) struct RuntimeConfig {
31
    pub(crate) is_human_readable: bool,
32
    pub(crate) is_named: bool,
33
    pub(crate) bytes: BytesMode,
34
}
35
36
/// When to encode `[u8]` as `bytes` rather than a sequence
37
/// of integers. Serde without `serde_bytes` has trouble
38
/// using `bytes`, and this is hack to force it. It may
39
/// break some data types.
40
#[non_exhaustive]
41
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
42
pub enum BytesMode {
43
    /// Use bytes only when Serde requires it
44
    /// (typically only when `serde_bytes` is used)
45
    #[default]
46
    Normal,
47
    /// Use bytes for slices, `Vec`, and a few other types that
48
    /// use `Iterator` in Serde.
49
    ///
50
    /// This may break some implementations of `Deserialize`.
51
    ///
52
    /// This does not include fixed-length arrays.
53
    ForceIterables,
54
    /// Use bytes for everything that looks like a container of `u8`.
55
    /// This breaks some implementations of `Deserialize`.
56
    ForceAll,
57
}
58
59
impl RuntimeConfig {
60
0
    pub(crate) fn new(other: impl sealed::SerializerConfig) -> Self {
61
0
        Self {
62
0
            is_human_readable: other.is_human_readable(),
63
0
            is_named: other.is_named(),
64
0
            bytes: other.bytes(),
65
0
        }
66
0
    }
67
}
68
69
impl sealed::SerializerConfig for RuntimeConfig {
70
    #[inline]
71
0
    fn is_human_readable(&self) -> bool {
72
0
        self.is_human_readable
73
0
    }
74
75
    #[inline]
76
0
    fn is_named(&self) -> bool {
77
0
        self.is_named
78
0
    }
79
80
    #[inline]
81
0
    fn bytes(&self) -> BytesMode {
82
0
        self.bytes
83
0
    }
84
}
85
86
/// The default serializer/deserializer configuration.
87
///
88
/// This configuration:
89
/// - Writes structs as a tuple, without field names
90
/// - Writes enum variants as integers
91
/// - Writes and reads types as binary, not human-readable
92
//
93
/// This is the most compact representation.
94
#[derive(Copy, Clone, Debug)]
95
pub struct DefaultConfig;
96
97
impl sealed::SerializerConfig for DefaultConfig {
98
    #[inline(always)]
99
0
    fn is_named(&self) -> bool {
100
0
        false
101
0
    }
102
103
    #[inline(always)]
104
0
    fn is_human_readable(&self) -> bool {
105
0
        false
106
0
    }
107
108
    #[inline(always)]
109
0
    fn bytes(&self) -> BytesMode {
110
0
        BytesMode::default()
111
0
    }
112
}
113
114
/// Config wrapper, that overrides struct serialization by packing as a map with field names.
115
///
116
/// MessagePack specification does not tell how to serialize structs. This trait allows you to
117
/// extend serialization to match your app's requirements.
118
///
119
/// Default `Serializer` implementation writes structs as a tuple, i.e. only its length is encoded,
120
/// because it is the most compact representation.
121
#[derive(Copy, Clone, Debug)]
122
pub struct StructMapConfig<C>(C);
123
124
impl<C> StructMapConfig<C> {
125
    /// Creates a `StructMapConfig` inheriting unchanged configuration options from the given configuration.
126
    #[inline]
127
0
    pub fn new(inner: C) -> Self {
128
0
        StructMapConfig(inner)
129
0
    }
130
}
131
132
impl<C> sealed::SerializerConfig for StructMapConfig<C>
133
where
134
    C: sealed::SerializerConfig,
135
{
136
    #[inline(always)]
137
0
    fn is_named(&self) -> bool {
138
0
        true
139
0
    }
140
141
    #[inline(always)]
142
0
    fn is_human_readable(&self) -> bool {
143
0
        self.0.is_human_readable()
144
0
    }
145
146
0
    fn bytes(&self) -> BytesMode {
147
0
        self.0.bytes()
148
0
    }
149
}
150
151
/// Config wrapper that overrides struct serlization by packing as a tuple without field
152
/// names.
153
#[derive(Copy, Clone, Debug)]
154
pub struct StructTupleConfig<C>(C);
155
156
impl<C> StructTupleConfig<C> {
157
    /// Creates a `StructTupleConfig` inheriting unchanged configuration options from the given configuration.
158
    #[inline]
159
0
    pub fn new(inner: C) -> Self {
160
0
        StructTupleConfig(inner)
161
0
    }
162
}
163
164
impl<C> sealed::SerializerConfig for StructTupleConfig<C>
165
where
166
    C: sealed::SerializerConfig,
167
{
168
    #[inline(always)]
169
0
    fn is_named(&self) -> bool {
170
0
        false
171
0
    }
172
173
    #[inline(always)]
174
0
    fn is_human_readable(&self) -> bool {
175
0
        self.0.is_human_readable()
176
0
    }
177
178
0
    fn bytes(&self) -> BytesMode {
179
0
        self.0.bytes()
180
0
    }
181
}
182
183
/// Config wrapper that overrides `Serializer::is_human_readable` and
184
/// `Deserializer::is_human_readable` to return `true`.
185
#[derive(Copy, Clone, Debug)]
186
pub struct HumanReadableConfig<C>(C);
187
188
impl<C> HumanReadableConfig<C> {
189
    /// Creates a `HumanReadableConfig` inheriting unchanged configuration options from the given configuration.
190
    #[inline]
191
0
    pub fn new(inner: C) -> Self {
192
0
        Self(inner)
193
0
    }
194
}
195
196
impl<C> sealed::SerializerConfig for HumanReadableConfig<C>
197
where
198
    C: sealed::SerializerConfig,
199
{
200
    #[inline(always)]
201
0
    fn is_named(&self) -> bool {
202
0
        self.0.is_named()
203
0
    }
204
205
    #[inline(always)]
206
0
    fn is_human_readable(&self) -> bool {
207
0
        true
208
0
    }
209
210
0
    fn bytes(&self) -> BytesMode {
211
0
        self.0.bytes()
212
0
    }
213
}
214
215
/// Config wrapper that overrides `Serializer::is_human_readable` and
216
/// `Deserializer::is_human_readable` to return `false`.
217
#[derive(Copy, Clone, Debug)]
218
pub struct BinaryConfig<C>(C);
219
220
impl<C> BinaryConfig<C> {
221
    /// Creates a `BinaryConfig` inheriting unchanged configuration options from the given configuration.
222
    #[inline(always)]
223
0
    pub fn new(inner: C) -> Self {
224
0
        Self(inner)
225
0
    }
226
}
227
228
impl<C> sealed::SerializerConfig for BinaryConfig<C>
229
where
230
    C: sealed::SerializerConfig,
231
{
232
    #[inline(always)]
233
0
    fn is_named(&self) -> bool {
234
0
        self.0.is_named()
235
0
    }
236
237
    #[inline(always)]
238
0
    fn is_human_readable(&self) -> bool {
239
0
        false
240
0
    }
241
242
0
    fn bytes(&self) -> BytesMode {
243
0
        self.0.bytes()
244
0
    }
245
}