tinc/private/
enum_.rs

1use std::collections::{BTreeMap, HashMap};
2use std::marker::PhantomData;
3
4use super::{DeserializeContent, DeserializeHelper, Expected, Tracker, TrackerDeserializer, TrackerFor};
5
6pub struct EnumTracker<T>(PhantomData<T>);
7
8impl<T> std::fmt::Debug for EnumTracker<T> {
9    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10        write!(f, "EnumTracker<{}>", std::any::type_name::<T>())
11    }
12}
13
14impl<T> Default for EnumTracker<T> {
15    fn default() -> Self {
16        Self(PhantomData)
17    }
18}
19
20impl<T> Tracker for EnumTracker<T> {
21    type Target = i32;
22
23    fn allow_duplicates(&self) -> bool {
24        false
25    }
26}
27
28pub trait EnumHelper {
29    type Target<E>;
30}
31
32#[repr(transparent)]
33pub struct Enum<T> {
34    value: i32,
35    _marker: PhantomData<T>,
36}
37
38impl<T: TryFrom<i32> + Default + std::fmt::Debug> std::fmt::Debug for Enum<T> {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        write!(f, "Enum({:?})", T::try_from(self.value).unwrap_or_default())
41    }
42}
43
44impl<T: Expected> Expected for Enum<T> {
45    fn expecting(formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
46        write!(formatter, "an enum of `")?;
47        T::expecting(formatter)?;
48        write!(formatter, "`")
49    }
50}
51
52impl<T> Default for Enum<T> {
53    fn default() -> Self {
54        Self {
55            value: Default::default(),
56            _marker: PhantomData,
57        }
58    }
59}
60
61impl<T> TrackerFor for Enum<T> {
62    type Tracker = EnumTracker<T>;
63}
64
65impl EnumHelper for i32 {
66    type Target<E> = Enum<E>;
67}
68
69impl EnumHelper for Option<i32> {
70    type Target<E> = Option<Enum<E>>;
71}
72
73impl EnumHelper for Vec<i32> {
74    type Target<E> = Vec<Enum<E>>;
75}
76
77impl<K: Ord> EnumHelper for BTreeMap<K, i32> {
78    type Target<E> = BTreeMap<K, Enum<E>>;
79}
80
81impl<K, S> EnumHelper for HashMap<K, i32, S> {
82    type Target<E> = HashMap<K, Enum<E>, S>;
83}
84
85impl<'de, T> serde::de::DeserializeSeed<'de> for DeserializeHelper<'_, EnumTracker<T>>
86where
87    T: serde::Deserialize<'de> + Into<i32>,
88{
89    type Value = ();
90
91    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
92    where
93        D: serde::Deserializer<'de>,
94    {
95        *self.value = T::deserialize(deserializer)?.into();
96        Ok(())
97    }
98}
99
100impl<'de, T> TrackerDeserializer<'de> for EnumTracker<T>
101where
102    T: serde::Deserialize<'de> + Into<i32>,
103{
104    fn deserialize<D>(&mut self, value: &mut Self::Target, deserializer: D) -> Result<(), D::Error>
105    where
106        D: DeserializeContent<'de>,
107    {
108        deserializer.deserialize_seed(DeserializeHelper { value, tracker: self })
109    }
110}
111
112use serde::Serialize;
113
114impl<T> serde::Serialize for Enum<T>
115where
116    T: Serialize + TryFrom<i32>,
117{
118    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
119    where
120        S: serde::Serializer,
121    {
122        let value = T::try_from(self.value).map_err(|_| serde::ser::Error::custom("invalid enum value"))?;
123        value.serialize(serializer)
124    }
125}
126
127/// # Safety
128/// This trait is marked as unsafe because the implementator
129/// must ensure that Helper has the same layout & memory representation as Self.
130unsafe trait EnumSerialize<T> {
131    type Helper: Serialize;
132
133    fn cast(&self) -> &Self::Helper {
134        // Safety: This trait is marked as unsafe and that safety condition
135        // makes this operation safe.
136        unsafe { &*(self as *const Self as *const Self::Helper) }
137    }
138}
139
140/// Safety: [`Enum`] is `#[repr(transparent)]` for [`i32`].
141unsafe impl<T: Serialize + TryFrom<i32>> EnumSerialize<T> for i32 {
142    type Helper = Enum<T>;
143}
144
145/// Safety: [`Enum`] is `#[repr(transparent)]` for [`i32`].
146unsafe impl<T: Serialize + TryFrom<i32>> EnumSerialize<T> for Option<i32> {
147    type Helper = Option<Enum<T>>;
148}
149
150/// Safety: [`Enum`] is `#[repr(transparent)]` for [`i32`].
151unsafe impl<T: Serialize + TryFrom<i32>> EnumSerialize<T> for Vec<i32> {
152    type Helper = Vec<Enum<T>>;
153}
154
155/// Safety: [`Enum`] is `#[repr(transparent)]` for [`i32`].
156unsafe impl<K: Serialize, V: Serialize + TryFrom<i32>> EnumSerialize<V> for BTreeMap<K, i32> {
157    type Helper = BTreeMap<K, Enum<V>>;
158}
159
160/// Safety: [`Enum`] is `#[repr(transparent)]` for [`i32`].
161unsafe impl<K: Serialize, V: Serialize + TryFrom<i32>> EnumSerialize<V> for HashMap<K, i32> {
162    type Helper = HashMap<K, Enum<V>>;
163}
164
165#[allow(private_bounds)]
166pub fn serialize_enum<T, V, S>(value: &V, serializer: S) -> Result<S::Ok, S::Error>
167where
168    V: EnumSerialize<T>,
169    S: serde::Serializer,
170{
171    value.cast().serialize(serializer)
172}