musli/serde/
mod.rs

1//! Transparent [`serde`] support for Müsli types.
2//!
3//! This conveniently and transparently allows Müsli to use fields which are
4//! serde types by marking them with  `#[musli(with = musli::serde)]`. This can
5//! be useful because there is a wide ecosystem of types which implements serde
6//! traits.
7//!
8//! Note that the exact method that fields are serialized and deserialized will
9//! not match what Müsli does, since serde requires the use of a fundamentally
10//! different model and Müsli metadata such as `#[musli(name = ..)]` is not
11//! available in [`serde`].
12//!
13//! [`serde`]: https://serde.rs
14//!
15//! <br>
16//!
17//! ## Examples
18//!
19//! ```
20//! use serde::{Serialize, Deserialize};
21//! use musli::{Encode, Decode};
22//! use url::Url;
23//!
24//! #[derive(Serialize, Deserialize)]
25//! struct Address {
26//!     street: String,
27//!     city: String,
28//!     zip: u32,
29//! }
30//!
31//! #[derive(Encode, Decode)]
32//! #[musli(name_all = "name")]
33//! struct Person {
34//!     name: String,
35//!     #[musli(with = musli::serde)]
36//!     address: Address,
37//!     #[musli(with = musli::serde)]
38//!     url: Url,
39//! }
40//! ```
41//!
42//! A compatible Müsli structure would look like this:
43//!
44//! ```
45//! use musli::{Encode, Decode};
46//! use url::Url;
47//! # use serde::{Serialize, Deserialize};
48//! # #[derive(Serialize, Deserialize)]
49//! # struct Address { street: String, city: String, zip: u32 }
50//! # #[derive(Encode, Decode)]
51//! # #[musli(name_all = "name")]
52//! # struct Person { name: String, #[musli(with = musli::serde)] address: Address, #[musli(with = musli::serde)] url: Url }
53//!
54//! #[derive(Encode, Decode)]
55//! #[musli(name_all = "name")]
56//! struct MusliAddress {
57//!     street: String,
58//!     city: String,
59//!     zip: u32,
60//! }
61//!
62//! #[derive(Encode, Decode)]
63//! #[musli(name_all = "name")]
64//! struct MusliPerson {
65//!     name: String,
66//!     address: MusliAddress,
67//!     url: String,
68//! }
69//!
70//! let json = musli::json::to_string(&Person {
71//!     name: "John Doe".to_string(),
72//!     address: Address {
73//!         street: "Main St.".to_string(),
74//!         city: "Springfield".to_string(),
75//!         zip: 12345,
76//!     },
77//!     url: Url::parse("https://example.com")?,
78//! })?;
79//!
80//! let musli = musli::json::from_str::<MusliPerson>(&json)?;
81//!
82//! assert_eq!(musli.name, "John Doe");
83//! assert_eq!(musli.address.street, "Main St.");
84//! assert_eq!(musli.address.city, "Springfield");
85//! assert_eq!(musli.address.zip, 12345);
86//! assert_eq!(musli.url, "https://example.com/");
87//! # Ok::<_, Box<dyn core::error::Error>>(())
88//! ```
89
90#![cfg(feature = "serde")]
91#![cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
92
93mod de;
94mod error;
95mod ser;
96
97use serde::{Deserialize, Serialize};
98
99use self::de::Deserializer;
100use self::ser::Serializer;
101
102use crate::{Decoder, Encoder};
103
104/// Encode the given serde value `T` to the given [`Encoder`] using the serde
105/// compatibility layer.
106///
107/// ## Examples
108///
109/// ```
110/// use serde::{Serialize, Deserialize};
111/// use musli::{Encode, Decode};
112/// use url::Url;
113///
114/// #[derive(Serialize, Deserialize)]
115/// struct Address {
116///     street: String,
117///     city: String,
118///     zip: u32,
119/// }
120///
121/// #[derive(Encode, Decode)]
122/// #[musli(name_all = "name")]
123/// struct Person {
124///     name: String,
125///     #[musli(with = musli::serde)]
126///     address: Address,
127///     #[musli(with = musli::serde)]
128///     url: Url,
129/// }
130/// ```
131#[inline]
132pub fn encode<E, T>(value: &T, encoder: E) -> Result<(), E::Error>
133where
134    E: Encoder,
135    T: Serialize,
136{
137    let cx = encoder.cx();
138    let serializer = Serializer::new(encoder);
139    value.serialize(serializer).map_err(error::err(cx))
140}
141
142/// Decode the given serde value `T` from the given [`Decoder`] using the serde
143/// compatibility layer.
144///
145/// ## Examples
146///
147/// ```
148/// use serde::{Serialize, Deserialize};
149/// use musli::{Encode, Decode};
150/// use url::Url;
151///
152/// #[derive(Serialize, Deserialize)]
153/// struct Address {
154///     street: String,
155///     city: String,
156///     zip: u32,
157/// }
158///
159/// #[derive(Encode, Decode)]
160/// #[musli(name_all = "name")]
161/// struct Person {
162///     name: String,
163///     #[musli(with = musli::serde)]
164///     address: Address,
165///     #[musli(with = musli::serde)]
166///     url: Url,
167/// }
168/// ```
169#[inline]
170pub fn decode<'de, D, T>(decoder: D) -> Result<T, D::Error>
171where
172    D: Decoder<'de>,
173    T: Deserialize<'de>,
174{
175    let cx = decoder.cx();
176    let deserializer = Deserializer::new(decoder);
177    T::deserialize(deserializer).map_err(error::err(cx))
178}