serde_partial/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
4
5#[cfg(feature = "alloc")]
6extern crate alloc;
7#[cfg(feature = "std")]
8extern crate std;
9
10use core::{cmp, fmt, hash, marker::PhantomData};
11
12use serde::ser::{Serialize, Serializer};
13
14#[cfg(feature = "alloc")]
15#[cfg_attr(feature = "alloc", path = "alloc.rs")]
16mod feature_alloc;
17#[cfg(feature = "std")]
18#[cfg_attr(feature = "std", path = "std.rs")]
19mod feature_std;
20#[path = "map.rs"]
21mod serde_map;
22#[path = "struct.rs"]
23mod serde_struct;
24
25pub mod filter;
26pub use filter::SerializeFilter;
27
28/// Derive macro for the [`SerializePartial`] trait.
29pub use serde_partial_macro::SerializePartial;
30
31/// Trait implemented by types which can be partially serialized.
32pub trait SerializePartial<'a>: Serialize {
33    /// Type which provides the list of serializable fields.
34    ///
35    /// When using the derive macro, this type is a struct with the same fields as the original struct.
36    /// It will implement [`IntoIterator`] to make it possible to iterate over the available fields, and [`Copy`] and [`Clone`] for convenience.
37    /// It will also have a `FIELDS: Self` associated constant.
38    type Fields: 'a;
39    /// Type which can be used to check whether a serializable field should be skipped.
40    type Filter: SerializeFilter<Self> + 'a;
41
42    /// Returns a value which forwards the [`Serialize`] implementation but only serializes the selected fields.
43    ///
44    /// The `select` closure receives an instance of [`Fields`][SerializePartial::Fields] which can than be used to select which fields should be serialized.
45    /// The closure can return any type which implements [`IntoIterator`]. This could be an array, but could also be a `Vec` or an [`Iterator`] with fields selected at runtime.
46    ///
47    /// ## Example
48    ///
49    /// ```
50    /// use serde::Serialize;
51    /// use serde_partial::SerializePartial;
52    ///
53    /// #[derive(Serialize, SerializePartial)]
54    /// #[serde(rename_all = "camelCase")]
55    /// struct User {
56    ///     full_name: &'static str,
57    ///     age: u8,
58    ///     #[serde(rename = "contact")]
59    ///     email: &'static str,
60    /// }
61    ///
62    /// const USER: User = User {
63    ///     full_name: "John Doe",
64    ///     age: 42,
65    ///     email: "john.doe@example.com",
66    /// };
67    ///
68    /// // serialize only the `full_name` field
69    /// let filtered = USER.with_fields(|u| [u.full_name]);
70    /// let json = serde_json::to_value(&filtered).unwrap();
71    /// assert_eq!(
72    ///     json,
73    ///     serde_json::json!({
74    ///         "fullName": USER.full_name,
75    ///     })
76    /// );
77    ///
78    /// // the field list doesn't have to be an array
79    /// // serialize every field with a name longer than 4 characters
80    /// let filtered = USER.with_fields(|u| u.into_iter().filter(|f| f.name().len() > 4));
81    /// let json = serde_json::to_value(&filtered).unwrap();
82    /// assert_eq!(
83    ///     json,
84    ///     serde_json::json!({
85    ///         "fullName": USER.full_name,
86    ///         "contact": USER.email,
87    ///     })
88    /// );
89    ///
90    /// // field names respect serde attributes
91    /// assert_eq!(<User as SerializePartial>::Fields::FIELDS.full_name.name(), "fullName");
92    /// assert_eq!(<User as SerializePartial>::Fields::FIELDS.age.name(), "age");
93    /// assert_eq!(<User as SerializePartial>::Fields::FIELDS.email.name(), "contact");
94    /// ```
95    fn with_fields<F, I>(&'a self, select: F) -> Partial<'a, Self>
96    where
97        F: FnOnce(Self::Fields) -> I,
98        I: IntoIterator<Item = Field<'a, Self>>;
99
100    /// Same as [`with_fields`][SerializePartial::with_fields] but fields are opt-out instead of opt-in.
101    ///
102    /// ## Example
103    ///
104    /// ```
105    /// # use serde::Serialize;
106    /// # use serde_partial::SerializePartial;
107    /// #
108    /// # #[derive(Serialize, SerializePartial)]
109    /// # #[serde(rename_all = "camelCase")]
110    /// # struct User {
111    /// #     full_name: &'static str,
112    /// #     age: u8,
113    /// #     #[serde(rename = "contact")]
114    /// #     email: &'static str,
115    /// # }
116    /// #
117    /// # const USER: User = User {
118    /// #     full_name: "John Doe",
119    /// #     age: 42,
120    /// #     email: "john.doe@example.com",
121    /// # };
122    /// #
123    /// let filtered = USER.without_fields(|u| [u.email]);
124    /// let json = serde_json::to_value(&filtered).unwrap();
125    /// assert_eq!(
126    ///     json,
127    ///     serde_json::json!({
128    ///         "fullName": USER.full_name,
129    ///         "age": USER.age,
130    ///     })
131    /// );
132    /// ```
133    fn without_fields<F, I>(
134        &'a self,
135        select: F,
136    ) -> Partial<'a, Self, filter::InverseFilter<'a, Self>>
137    where
138        F: FnOnce(Self::Fields) -> I,
139        I: IntoIterator<Item = Field<'a, Self>>,
140    {
141        let Partial { value, filter } = self.with_fields(select);
142        Partial {
143            value,
144            filter: filter::InverseFilter::new(filter),
145        }
146    }
147}
148
149/// A type which implements [`Serialize`] by forwarding the implementation to the value it references while skipping fields according to its filter.
150#[derive(Debug)]
151pub struct Partial<'a, T, F = <T as SerializePartial<'a>>::Filter>
152where
153    T: ?Sized + SerializePartial<'a>,
154{
155    /// The value to serialize.
156    pub value: &'a T,
157    /// The field filter to use.
158    pub filter: F,
159}
160
161/// Newtype around a field name for the specified type.
162#[repr(transparent)]
163pub struct Field<'a, T: ?Sized> {
164    name: &'a str,
165    _ty: PhantomData<T>,
166}
167
168impl<'a, T, F> Clone for Partial<'a, T, F>
169where
170    T: ?Sized + SerializePartial<'a>,
171    F: Clone,
172{
173    fn clone(&self) -> Self {
174        Self {
175            value: self.value,
176            filter: self.filter.clone(),
177        }
178    }
179}
180impl<'a, T, F> Copy for Partial<'a, T, F>
181where
182    T: ?Sized + SerializePartial<'a>,
183    F: Copy,
184{
185}
186
187impl<'a, T: ?Sized> Field<'a, T> {
188    /// Creates a new field.
189    ///
190    /// The name should be the serde field name and not the Rust field name.
191    pub const fn new(name: &'a str) -> Self {
192        Self {
193            name,
194            _ty: PhantomData,
195        }
196    }
197
198    /// Returns the field name.
199    pub const fn name(&self) -> &'a str {
200        self.name
201    }
202}
203
204impl<T: ?Sized> Clone for Field<'_, T> {
205    fn clone(&self) -> Self {
206        Self {
207            name: self.name,
208            _ty: PhantomData,
209        }
210    }
211}
212impl<T: ?Sized> Copy for Field<'_, T> {}
213
214impl<T: ?Sized> fmt::Debug for Field<'_, T> {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        f.debug_struct("Field")
217            .field("name", &self.name)
218            .field("container", &core::any::type_name::<T>())
219            .finish()
220    }
221}
222
223impl<T: ?Sized> PartialEq for Field<'_, T> {
224    fn eq(&self, other: &Self) -> bool {
225        self.name == other.name
226    }
227}
228impl<T: ?Sized> Eq for Field<'_, T> {}
229impl<T: ?Sized> hash::Hash for Field<'_, T> {
230    fn hash<H: hash::Hasher>(&self, state: &mut H) {
231        self.name.hash(state);
232    }
233}
234impl<T: ?Sized> PartialOrd for Field<'_, T> {
235    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
236        self.name.partial_cmp(other.name)
237    }
238}
239impl<T: ?Sized> Ord for Field<'_, T> {
240    fn cmp(&self, other: &Self) -> cmp::Ordering {
241        self.name.cmp(other.name)
242    }
243}
244
245impl<T, F> Serialize for Partial<'_, T, F>
246where
247    T: ?Sized + for<'a> SerializePartial<'a>,
248    F: SerializeFilter<T>,
249{
250    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
251    where
252        S: Serializer,
253    {
254        let serializer = PartialSerializer {
255            s: serializer,
256            filter: &self.filter,
257            _ty: PhantomData,
258        };
259        self.value.serialize(serializer)
260    }
261}
262
263struct PartialSerializer<'a, S, T, F>
264where
265    S: Serializer,
266    T: ?Sized,
267{
268    s: S,
269    filter: &'a F,
270    _ty: PhantomData<T>,
271}
272
273impl<'a, S, T, F> Serializer for PartialSerializer<'a, S, T, F>
274where
275    S: Serializer,
276    T: ?Sized + for<'p> SerializePartial<'p>,
277    F: SerializeFilter<T>,
278{
279    type Ok = S::Ok;
280    type Error = S::Error;
281
282    type SerializeStruct = serde_struct::PartialSerializeStruct<'a, S, T, F>;
283    type SerializeMap = serde_map::PartialSerializeMap<'a, S, T, F>;
284
285    fn serialize_struct(
286        self,
287        name: &'static str,
288        len: usize,
289    ) -> Result<Self::SerializeStruct, Self::Error> {
290        let PartialSerializer { s, filter, _ty } = self;
291        let len = filter.filtered_len(Some(len)).unwrap_or(len);
292        let ss = s.serialize_struct(name, len)?;
293        Ok(Self::SerializeStruct { ss, filter, _ty })
294    }
295
296    fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
297        let PartialSerializer { s, filter, _ty } = self;
298        let len = filter.filtered_len(len).or(len);
299        let sm = s.serialize_map(len)?;
300        Ok(Self::SerializeMap { sm, filter, _ty })
301    }
302    // collect_map not implemented because we explicitly want serde's default implementation
303
304    type SerializeSeq = S::SerializeSeq;
305    type SerializeTuple = S::SerializeTuple;
306    type SerializeTupleStruct = S::SerializeTupleStruct;
307    type SerializeTupleVariant = S::SerializeTupleVariant;
308    type SerializeStructVariant = S::SerializeStructVariant;
309
310    fn is_human_readable(&self) -> bool {
311        self.s.is_human_readable()
312    }
313    fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
314        self.s.serialize_bool(v)
315    }
316    fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
317        self.s.serialize_i8(v)
318    }
319    fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
320        self.s.serialize_i16(v)
321    }
322    fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
323        self.s.serialize_i32(v)
324    }
325    fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
326        self.s.serialize_i64(v)
327    }
328    fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
329        self.s.serialize_i128(v)
330    }
331    fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
332        self.s.serialize_u8(v)
333    }
334    fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
335        self.s.serialize_u16(v)
336    }
337    fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
338        self.s.serialize_u32(v)
339    }
340    fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
341        self.s.serialize_u64(v)
342    }
343    fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
344        self.s.serialize_u128(v)
345    }
346    fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
347        self.s.serialize_f32(v)
348    }
349    fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
350        self.s.serialize_f64(v)
351    }
352    fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
353        self.s.serialize_char(v)
354    }
355    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
356        self.s.serialize_str(v)
357    }
358    fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
359        self.s.serialize_bytes(v)
360    }
361    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
362        self.s.serialize_none()
363    }
364    fn serialize_some<TT: ?Sized>(self, value: &TT) -> Result<Self::Ok, Self::Error>
365    where
366        TT: Serialize,
367    {
368        self.s.serialize_some(value)
369    }
370    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
371        self.s.serialize_unit()
372    }
373    fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
374        self.s.serialize_unit_struct(name)
375    }
376    fn serialize_unit_variant(
377        self,
378        name: &'static str,
379        index: u32,
380        variant: &'static str,
381    ) -> Result<Self::Ok, Self::Error> {
382        self.s.serialize_unit_variant(name, index, variant)
383    }
384    fn serialize_newtype_struct<TT: ?Sized>(
385        self,
386        name: &'static str,
387        value: &TT,
388    ) -> Result<Self::Ok, Self::Error>
389    where
390        TT: Serialize,
391    {
392        self.s.serialize_newtype_struct(name, value)
393    }
394    fn serialize_newtype_variant<TT: ?Sized>(
395        self,
396        name: &'static str,
397        index: u32,
398        variant: &'static str,
399        value: &TT,
400    ) -> Result<Self::Ok, Self::Error>
401    where
402        TT: Serialize,
403    {
404        self.s
405            .serialize_newtype_variant(name, index, variant, value)
406    }
407    fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
408        self.s.serialize_seq(len)
409    }
410    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
411        self.s.serialize_tuple(len)
412    }
413    fn serialize_tuple_struct(
414        self,
415        name: &'static str,
416        len: usize,
417    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
418        self.s.serialize_tuple_struct(name, len)
419    }
420    fn serialize_tuple_variant(
421        self,
422        name: &'static str,
423        index: u32,
424        variant: &'static str,
425        len: usize,
426    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
427        self.s.serialize_tuple_variant(name, index, variant, len)
428    }
429    fn serialize_struct_variant(
430        self,
431        name: &'static str,
432        index: u32,
433        variant: &'static str,
434        len: usize,
435    ) -> Result<Self::SerializeStructVariant, Self::Error> {
436        self.s.serialize_struct_variant(name, index, variant, len)
437    }
438    fn collect_str<TT: ?Sized>(self, value: &TT) -> Result<Self::Ok, Self::Error>
439    where
440        TT: fmt::Display,
441    {
442        self.s.collect_str(value)
443    }
444    fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error>
445    where
446        I: IntoIterator,
447        <I as IntoIterator>::Item: Serialize,
448    {
449        self.s.collect_seq(iter)
450    }
451}