serdapt/
option.rs

1// Copyright (c) 2024 Stephane Raux. Distributed under the 0BSD license.
2
3use crate::{DeserializeWith, SerializeWith, WithEncoding};
4use core::marker::PhantomData;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6
7/// Adapter for [`Option`](core::option::Option)
8///
9/// # Example
10/// ```
11/// use serdapt as sa;
12/// use serde::{Deserialize, Serialize};
13/// use serde_json::json;
14///
15/// #[derive(Deserialize, Serialize)]
16/// struct Foo(#[serde(with = "sa::Option::<sa::Str>")] Option<i32>);
17///
18/// let v = serde_json::to_value(Foo(Some(33))).unwrap();
19/// assert_eq!(v, json!("33"));
20/// ```
21pub struct Option<F>(PhantomData<F>);
22
23impl<F> Option<F> {
24    /// Serializes value with adapter
25    pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
26    where
27        T: ?Sized,
28        S: Serializer,
29        Self: SerializeWith<T>,
30    {
31        Self::serialize_with(value, serializer)
32    }
33
34    /// Deserializes value with adapter
35    pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
36    where
37        D: Deserializer<'de>,
38        Self: DeserializeWith<'de, T>,
39    {
40        Self::deserialize_with(deserializer)
41    }
42}
43
44impl<F, T> SerializeWith<core::option::Option<T>> for Option<F>
45where
46    F: SerializeWith<T>,
47{
48    fn serialize_with<S: Serializer>(
49        value: &core::option::Option<T>,
50        serializer: S,
51    ) -> Result<S::Ok, S::Error> {
52        let value = value.as_ref().map(WithEncoding::<&F, &T>::from);
53        Serialize::serialize(&value, serializer)
54    }
55}
56
57impl<'de, F, T> DeserializeWith<'de, core::option::Option<T>> for Option<F>
58where
59    F: DeserializeWith<'de, T>,
60{
61    fn deserialize_with<D>(deserializer: D) -> Result<core::option::Option<T>, D::Error>
62    where
63        D: Deserializer<'de>,
64    {
65        let x: core::option::Option<WithEncoding<F, T>> = Deserialize::deserialize(deserializer)?;
66        Ok(x.map(WithEncoding::into_inner))
67    }
68}