rmp_serde/
lib.rs

1#![doc = include_str!("../README.md")]
2#![forbid(unsafe_code)]
3#![warn(missing_debug_implementations, missing_docs)]
4#![allow(clippy::bool_assert_comparison)]
5#![allow(clippy::derive_partial_eq_without_eq)]
6#![allow(clippy::doc_markdown)]
7#![allow(clippy::match_same_arms)]
8
9use std::fmt::{self, Display, Formatter};
10use std::str::{self, Utf8Error};
11
12use serde::{de, Deserialize, Serialize};
13
14#[allow(deprecated)]
15pub use crate::decode::from_read_ref;
16pub use crate::decode::{from_read, Deserializer};
17pub use crate::encode::{to_vec, to_vec_named, Serializer};
18
19pub use crate::decode::from_slice;
20
21mod bytes;
22pub mod config;
23pub mod decode;
24pub mod encode;
25
26/// Hack used to serialize MessagePack Extension types.
27///
28/// A special `ExtStruct` type is used to represent
29/// extension types. This struct is renamed in serde.
30///
31/// Name of Serde newtype struct to Represent Msgpack's Ext
32/// Msgpack Ext: `Ext(tag, binary)`
33/// Serde data model: `_ExtStruct((tag, binary))`
34///
35/// Example Serde impl for custom type:
36///
37/// ```ignore
38/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
39/// #[serde(rename = "_ExtStruct")]
40/// struct ExtStruct((i8, serde_bytes::ByteBuf));
41///
42/// test_round(ExtStruct((2, serde_bytes::ByteBuf::from(vec![5]))),
43///            Value::Ext(2, vec![5]));
44/// ```
45pub const MSGPACK_EXT_STRUCT_NAME: &str = "_ExtStruct";
46
47/// Helper that allows both to encode and decode strings no matter whether they contain valid or
48/// invalid UTF-8.
49///
50/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
51#[derive(Clone, Debug, PartialEq)]
52#[doc(hidden)]
53pub struct Raw {
54    s: Result<String, (Vec<u8>, Utf8Error)>,
55}
56
57impl Raw {
58    /// Constructs a new `Raw` from the UTF-8 string.
59    #[inline]
60    #[must_use]
61    pub fn new(v: String) -> Self {
62        Self { s: Ok(v) }
63    }
64
65    /// DO NOT USE. See <https://github.com/3Hren/msgpack-rust/issues/305>
66    #[deprecated(note = "This feature has been removed")]
67    #[must_use]
68    pub fn from_utf8(v: Vec<u8>) -> Self {
69        match String::from_utf8(v) {
70            Ok(v) => Self::new(v),
71            Err(err) => {
72                let e = err.utf8_error();
73                Self { s: Err((err.into_bytes(), e)) }
74            },
75        }
76    }
77
78    /// Returns `true` if the raw is valid UTF-8.
79    #[inline]
80    #[must_use]
81    pub fn is_str(&self) -> bool {
82        self.s.is_ok()
83    }
84
85    /// Returns `true` if the raw contains invalid UTF-8 sequence.
86    #[inline]
87    #[must_use]
88    pub fn is_err(&self) -> bool {
89        self.s.is_err()
90    }
91
92    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
93    #[inline]
94    #[must_use]
95    pub fn as_str(&self) -> Option<&str> {
96        match self.s {
97            Ok(ref s) => Some(s.as_str()),
98            Err(..) => None,
99        }
100    }
101
102    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
103    /// else `None`.
104    #[inline]
105    #[must_use]
106    pub fn as_err(&self) -> Option<&Utf8Error> {
107        match self.s {
108            Ok(..) => None,
109            Err((_, ref err)) => Some(err),
110        }
111    }
112
113    /// Returns a byte slice of this raw's contents.
114    #[inline]
115    #[must_use]
116    pub fn as_bytes(&self) -> &[u8] {
117        match self.s {
118            Ok(ref s) => s.as_bytes(),
119            Err(ref err) => &err.0[..],
120        }
121    }
122
123    /// Consumes this object, yielding the string if the raw is valid UTF-8, or else `None`.
124    #[inline]
125    #[must_use]
126    pub fn into_str(self) -> Option<String> {
127        self.s.ok()
128    }
129
130    /// Converts a `Raw` into a byte vector.
131    #[inline]
132    #[must_use]
133    pub fn into_bytes(self) -> Vec<u8> {
134        match self.s {
135            Ok(s) => s.into_bytes(),
136            Err(err) => err.0,
137        }
138    }
139}
140
141impl Serialize for Raw {
142    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
143    where
144        S: serde::Serializer,
145    {
146        match self.s {
147            Ok(ref s) => se.serialize_str(s),
148            Err((ref b, ..)) => se.serialize_bytes(b),
149        }
150    }
151}
152
153struct RawVisitor;
154
155impl de::Visitor<'_> for RawVisitor {
156    type Value = Raw;
157
158    #[cold]
159    fn expecting(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
160        "string or bytes".fmt(fmt)
161    }
162
163    #[inline]
164    fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
165        Ok(Raw { s: Ok(v) })
166    }
167
168    #[inline]
169    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
170        where E: de::Error
171    {
172        Ok(Raw { s: Ok(v.into()) })
173    }
174
175    #[inline]
176    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
177        where E: de::Error
178    {
179        let s = match str::from_utf8(v) {
180            Ok(s) => Ok(s.into()),
181            Err(err) => Err((v.into(), err)),
182        };
183
184        Ok(Raw { s })
185    }
186
187    #[inline]
188    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
189        where E: de::Error
190    {
191        let s = match String::from_utf8(v) {
192            Ok(s) => Ok(s),
193            Err(err) => {
194                let e = err.utf8_error();
195                Err((err.into_bytes(), e))
196            },
197        };
198
199        Ok(Raw { s })
200    }
201}
202
203impl<'de> Deserialize<'de> for Raw {
204    #[inline]
205    fn deserialize<D>(de: D) -> Result<Self, D::Error>
206        where D: de::Deserializer<'de>
207    {
208        de.deserialize_any(RawVisitor)
209    }
210}
211
212/// Helper that allows both to encode and decode strings no matter whether they contain valid or
213/// invalid UTF-8.
214///
215/// Regardless of validity the UTF-8 content this type will always be serialized as a string.
216#[derive(Clone, Copy, Debug, PartialEq)]
217#[doc(hidden)]
218pub struct RawRef<'a> {
219    s: Result<&'a str, (&'a [u8], Utf8Error)>,
220}
221
222impl<'a> RawRef<'a> {
223    /// Constructs a new `RawRef` from the UTF-8 string.
224    #[inline]
225    #[must_use]
226    pub fn new(v: &'a str) -> Self {
227        Self { s: Ok(v) }
228    }
229
230    #[deprecated(note = "This feature has been removed")]
231    #[must_use]
232    pub fn from_utf8(v: &'a [u8]) -> Self {
233        match str::from_utf8(v) {
234            Ok(v) => RawRef::new(v),
235            Err(err) => Self { s: Err((v, err)) },
236        }
237    }
238
239    /// Returns `true` if the raw is valid UTF-8.
240    #[inline]
241    #[must_use]
242    pub fn is_str(&self) -> bool {
243        self.s.is_ok()
244    }
245
246    /// Returns `true` if the raw contains invalid UTF-8 sequence.
247    #[inline]
248    #[must_use]
249    pub fn is_err(&self) -> bool {
250        self.s.is_err()
251    }
252
253    /// Returns the string reference if the raw is valid UTF-8, or else `None`.
254    #[inline]
255    #[must_use]
256    pub fn as_str(&self) -> Option<&str> {
257        self.s.ok()
258    }
259
260    /// Returns the underlying `Utf8Error` if the raw contains invalid UTF-8 sequence, or
261    /// else `None`.
262    #[inline]
263    #[must_use]
264    pub fn as_err(&self) -> Option<&Utf8Error> {
265        match self.s {
266            Ok(..) => None,
267            Err((_, ref err)) => Some(err),
268        }
269    }
270
271    /// Returns a byte slice of this raw's contents.
272    #[inline]
273    #[must_use]
274    pub fn as_bytes(&self) -> &[u8] {
275        match self.s {
276            Ok(s) => s.as_bytes(),
277            Err((bytes, _err)) => bytes,
278        }
279    }
280}
281
282impl Serialize for RawRef<'_> {
283    fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
284    where
285        S: serde::Serializer,
286    {
287        match self.s {
288            Ok(s) => se.serialize_str(s),
289            Err((b, ..)) => se.serialize_bytes(b),
290        }
291    }
292}
293
294struct RawRefVisitor;
295
296impl<'de> de::Visitor<'de> for RawRefVisitor {
297    type Value = RawRef<'de>;
298
299    #[cold]
300    fn expecting(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> {
301        "string or bytes".fmt(fmt)
302    }
303
304    #[inline]
305    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
306        where E: de::Error
307    {
308        Ok(RawRef { s: Ok(v) })
309    }
310
311    #[inline]
312    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
313        where E: de::Error
314    {
315        let s = match str::from_utf8(v) {
316            Ok(s) => Ok(s),
317            Err(err) => Err((v, err)),
318        };
319
320        Ok(RawRef { s })
321    }
322}
323
324impl<'de> Deserialize<'de> for RawRef<'de> {
325    #[inline]
326    fn deserialize<D>(de: D) -> Result<Self, D::Error>
327        where D: de::Deserializer<'de>
328    {
329        de.deserialize_any(RawRefVisitor)
330    }
331}