toml_datetime/
de.rs

1//! Deserialzation support for [`Datetime`][crate::Datetime]
2
3use alloc::string::ToString;
4
5use serde::de::value::BorrowedStrDeserializer;
6use serde::de::IntoDeserializer;
7
8/// Check if deserializing a [`Datetime`][crate::Datetime]
9pub fn is_datetime(name: &'static str) -> bool {
10    crate::datetime::is_datetime(name)
11}
12
13/// Deserializer / format support for emitting [`Datetime`][crate::Datetime]
14pub struct DatetimeDeserializer<E> {
15    date: Option<crate::Datetime>,
16    _error: core::marker::PhantomData<E>,
17}
18
19impl<E> DatetimeDeserializer<E> {
20    /// Create a deserializer to emit [`Datetime`][crate::Datetime]
21    pub fn new(date: crate::Datetime) -> Self {
22        Self {
23            date: Some(date),
24            _error: Default::default(),
25        }
26    }
27}
28
29impl<'de, E> serde::de::MapAccess<'de> for DatetimeDeserializer<E>
30where
31    E: serde::de::Error,
32{
33    type Error = E;
34
35    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
36    where
37        K: serde::de::DeserializeSeed<'de>,
38    {
39        if self.date.is_some() {
40            seed.deserialize(BorrowedStrDeserializer::new(crate::datetime::FIELD))
41                .map(Some)
42        } else {
43            Ok(None)
44        }
45    }
46
47    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
48    where
49        V: serde::de::DeserializeSeed<'de>,
50    {
51        if let Some(date) = self.date.take() {
52            seed.deserialize(date.to_string().into_deserializer())
53        } else {
54            panic!("next_value_seed called before next_key_seed")
55        }
56    }
57}
58
59/// Integrate [`Datetime`][crate::Datetime] into an untagged deserialize
60#[cfg(feature = "alloc")]
61pub enum VisitMap<'de> {
62    /// The map was deserialized as a [Datetime][crate::Datetime] value
63    Datetime(crate::Datetime),
64    /// The map is of an unknown format and needs further deserialization
65    Key(alloc::borrow::Cow<'de, str>),
66}
67
68impl<'de> VisitMap<'de> {
69    /// Determine the type of the map by deserializing it
70    pub fn next_key_seed<V: serde::de::MapAccess<'de>>(
71        visitor: &mut V,
72    ) -> Result<Option<Self>, V::Error> {
73        let mut key = None;
74        let Some(()) = visitor.next_key_seed(DatetimeOrTable::new(&mut key))? else {
75            return Ok(None);
76        };
77        let result = if let Some(key) = key {
78            VisitMap::Key(key)
79        } else {
80            let date: crate::datetime::DatetimeFromString = visitor.next_value()?;
81            VisitMap::Datetime(date.value)
82        };
83        Ok(Some(result))
84    }
85}
86
87struct DatetimeOrTable<'m, 'de> {
88    key: &'m mut Option<alloc::borrow::Cow<'de, str>>,
89}
90
91impl<'m, 'de> DatetimeOrTable<'m, 'de> {
92    fn new(key: &'m mut Option<alloc::borrow::Cow<'de, str>>) -> Self {
93        *key = None;
94        Self { key }
95    }
96}
97
98impl<'de> serde::de::DeserializeSeed<'de> for DatetimeOrTable<'_, 'de> {
99    type Value = ();
100
101    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
102    where
103        D: serde::de::Deserializer<'de>,
104    {
105        deserializer.deserialize_any(self)
106    }
107}
108
109impl<'de> serde::de::Visitor<'de> for DatetimeOrTable<'_, 'de> {
110    type Value = ();
111
112    fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113        formatter.write_str("a string key")
114    }
115
116    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
117    where
118        E: serde::de::Error,
119    {
120        if s == crate::datetime::FIELD {
121            *self.key = None;
122            Ok(())
123        } else {
124            use crate::alloc::borrow::ToOwned as _;
125            *self.key = Some(alloc::borrow::Cow::Owned(s.to_owned()));
126            Ok(())
127        }
128    }
129
130    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
131    where
132        E: serde::de::Error,
133    {
134        if s == crate::datetime::FIELD {
135            *self.key = None;
136            Ok(())
137        } else {
138            *self.key = Some(alloc::borrow::Cow::Borrowed(s));
139            Ok(())
140        }
141    }
142
143    #[allow(unused_qualifications)]
144    fn visit_string<E>(self, s: alloc::string::String) -> Result<Self::Value, E>
145    where
146        E: serde::de::Error,
147    {
148        if s == crate::datetime::FIELD {
149            *self.key = None;
150            Ok(())
151        } else {
152            *self.key = Some(alloc::borrow::Cow::Owned(s));
153            Ok(())
154        }
155    }
156}