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}