messpack_serde/
lib.rs

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