1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::{
    buffer::Buffer,
    deserialize::{Deserialize, DeserializeError, Deserializer},
    formula::{sum_size, BareFormula, Formula},
    serialize::{field_size_hint, write_bytes, write_field, Serialize, SerializeRef, Sizes},
};

impl<F> Formula for Option<F>
where
    F: Formula,
{
    const MAX_STACK_SIZE: Option<usize> = sum_size(Some(1), F::MAX_STACK_SIZE);
    const EXACT_SIZE: bool = matches!(F::MAX_STACK_SIZE, Some(0));
    const HEAPLESS: bool = F::HEAPLESS;
}

impl<F> BareFormula for Option<F> where F: Formula {}

impl<F, T> Serialize<Option<F>> for Option<T>
where
    F: Formula,
    T: Serialize<F>,
{
    #[inline(always)]
    fn serialize<B>(self, sizes: &mut Sizes, mut buffer: B) -> Result<(), B::Error>
    where
        B: Buffer,
    {
        match self {
            None => write_bytes(&[0u8], sizes, buffer),
            Some(value) => {
                write_bytes(&[1u8], sizes, buffer.reborrow())?;
                write_field::<F, T, _>(value, sizes, buffer, true)
            }
        }
    }

    #[inline(always)]
    fn size_hint(&self) -> Option<Sizes> {
        match self {
            None => {
                let stack = <Option<F>>::MAX_STACK_SIZE?;
                Some(Sizes::with_stack(stack))
            }
            Some(value) => {
                let mut sizes = field_size_hint::<F>(value, true)?;
                sizes.add_stack(1);
                Some(sizes)
            }
        }
    }
}

impl<F, T> SerializeRef<Option<F>> for Option<T>
where
    F: Formula,
    for<'ser> &'ser T: Serialize<F>,
{
    #[inline(always)]
    fn serialize<B>(&self, sizes: &mut Sizes, mut buffer: B) -> Result<(), B::Error>
    where
        B: Buffer,
    {
        match self {
            None => write_bytes(&[0u8], sizes, buffer),
            Some(value) => {
                write_bytes(&[1u8], sizes, buffer.reborrow())?;
                write_field::<F, &T, _>(value, sizes, buffer, true)
            }
        }
    }

    #[inline(always)]
    fn size_hint(&self) -> Option<Sizes> {
        match self {
            None => {
                let stack = <Option<F>>::MAX_STACK_SIZE?;
                Some(Sizes::with_stack(stack))
            }
            Some(value) => {
                let mut sizes = field_size_hint::<F>(&value, true)?;
                sizes.add_stack(1);
                Some(sizes)
            }
        }
    }
}

impl<'de, F, T> Deserialize<'de, Option<F>> for Option<T>
where
    F: Formula,
    T: Deserialize<'de, F>,
{
    #[inline(always)]
    fn deserialize(mut de: Deserializer<'de>) -> Result<Self, DeserializeError> {
        let is_some: u8 = de.read_bytes(1)?[0];
        if is_some == 0 {
            Ok(None)
        } else {
            Ok(Some(de.read_value::<F, T>(true)?))
        }
    }

    #[inline(always)]
    fn deserialize_in_place(&mut self, mut de: Deserializer<'de>) -> Result<(), DeserializeError> {
        let is_some: u8 = de.read_bytes(1)?[0];
        if is_some == 0 {
            *self = None;
        } else {
            match self {
                Some(value) => {
                    de.read_in_place::<F, T>(value, true)?;
                }
                None => {
                    *self = Some(de.read_value::<F, T>(true)?);
                }
            }
        }
        Ok(())
    }
}