Skip to main content

topcoat_runtime/surrogate/
option.rs

1use ref_cast::RefCast;
2
3use crate::{
4    BoolSurrogate, StrSurrogate, Surrogate, Surrogated, deserialize_tagged, impl_surrogate,
5    impl_surrogate_mut, impl_surrogate_ref, serialize_tagged,
6};
7
8#[derive(Debug, Clone, RefCast)]
9#[repr(transparent)]
10pub struct OptionSurrogate<T>(Option<T>);
11
12impl<T> OptionSurrogate<T> {
13    #[inline]
14    pub(crate) const fn new(v: Option<T>) -> Self {
15        Self(v)
16    }
17
18    #[inline]
19    pub fn none() -> Self {
20        Self(None)
21    }
22
23    #[inline]
24    pub fn is_some(&self) -> BoolSurrogate {
25        BoolSurrogate::new(self.0.is_some())
26    }
27
28    #[inline]
29    pub fn is_none(&self) -> BoolSurrogate {
30        BoolSurrogate::new(self.0.is_none())
31    }
32}
33
34impl<T> OptionSurrogate<T>
35where
36    T: Surrogated,
37{
38    #[inline]
39    pub fn some(v: impl Surrogate<Real = T>) -> Self {
40        Self(Some(v.into_real()))
41    }
42
43    /// Returns the contained value.
44    ///
45    /// # Panics
46    ///
47    /// Panics if the option is `None`.
48    #[inline]
49    #[track_caller]
50    pub fn unwrap(self) -> T::Surrogate {
51        self.0.unwrap().into_surrogate()
52    }
53
54    /// Returns the contained value, panicking with `msg` if `None`.
55    ///
56    /// # Panics
57    ///
58    /// Panics with `msg` if the option is `None`.
59    #[inline]
60    #[track_caller]
61    pub fn expect(self, msg: &StrSurrogate) -> T::Surrogate {
62        self.0.expect(&msg.0).into_surrogate()
63    }
64}
65
66impl_surrogate!({T} Option<T>, OptionSurrogate<T>);
67impl_surrogate_ref!({T} Option<T>, OptionSurrogate<T>);
68impl_surrogate_mut!({T} Option<T>, OptionSurrogate<T>);
69
70impl<T> serde::Serialize for OptionSurrogate<T>
71where
72    for<'a> &'a T: Surrogated,
73    for<'a> <&'a T as Surrogated>::Surrogate: serde::Serialize,
74{
75    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76    where
77        S: serde::Serializer,
78    {
79        let inner: Option<<&T as Surrogated>::Surrogate> =
80            self.0.as_ref().map(Surrogated::into_surrogate);
81        serialize_tagged(serializer, "Option", &inner)
82    }
83}
84
85impl<'de, T> serde::Deserialize<'de> for OptionSurrogate<T>
86where
87    T: Surrogated,
88    T::Surrogate: serde::Deserialize<'de>,
89{
90    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91    where
92        D: serde::Deserializer<'de>,
93    {
94        let inner: Option<T::Surrogate> = deserialize_tagged(deserializer, "Option")?;
95        Ok(Self(inner.map(Surrogate::into_real)))
96    }
97}