prusto_rs/types/
option.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use serde::de::{self, DeserializeSeed, Deserializer, Visitor};
5
6use super::{Context, Presto, PrestoTy};
7
8impl<T: Presto> Presto for Option<T> {
9    type ValueType<'a> = Option<T::ValueType<'a>> where T: 'a;
10    type Seed<'a, 'de> = OptionSeed<'a, T>;
11
12    fn value(&self) -> Self::ValueType<'_> {
13        self.as_ref().map(|t| t.value())
14    }
15
16    fn ty() -> PrestoTy {
17        PrestoTy::Option(Box::new(T::ty()))
18    }
19
20    fn seed<'a, 'de>(ctx: &'a Context) -> Self::Seed<'a, 'de> {
21        OptionSeed::new(ctx)
22    }
23
24    fn empty() -> Self {
25        None
26    }
27}
28
29pub struct OptionSeed<'a, T> {
30    ctx: &'a Context<'a>,
31    _marker: PhantomData<T>,
32}
33
34impl<'a, T> OptionSeed<'a, T> {
35    // caller must provide a valid `Context`
36    pub(super) fn new(ctx: &'a Context) -> Self {
37        OptionSeed {
38            ctx,
39            _marker: PhantomData,
40        }
41    }
42}
43
44impl<'a, 'de, T: Presto> Visitor<'de> for OptionSeed<'a, T> {
45    type Value = Option<T>;
46    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
47        formatter.write_str(T::ty().raw_type().to_str())
48    }
49
50    fn visit_none<E>(self) -> Result<Self::Value, E>
51    where
52        E: de::Error,
53    {
54        Ok(None)
55    }
56
57    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
58    where
59        D: Deserializer<'de>,
60    {
61        let seed = T::seed(self.ctx);
62        seed.deserialize(deserializer).map(Some)
63    }
64}
65
66impl<'a, 'de, T: Presto> DeserializeSeed<'de> for OptionSeed<'a, T> {
67    type Value = Option<T>;
68    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
69    where
70        D: Deserializer<'de>,
71    {
72        deserializer.deserialize_option(self)
73    }
74}