jomini/
de.rs

1use crate::{Error, binary::Rgb};
2use de::{DeserializeSeed, SeqAccess, Visitor};
3use serde::de;
4
5#[derive(Debug)]
6pub(crate) struct ColorSequence {
7    data: Rgb,
8    idx: usize,
9}
10
11impl ColorSequence {
12    pub(crate) fn new(data: Rgb) -> Self {
13        ColorSequence { data, idx: 0 }
14    }
15
16    fn val(&self) -> u32 {
17        match self.idx {
18            0 => self.data.r,
19            1 => self.data.g,
20            2 => self.data.b,
21            3 => self.data.a.unwrap(),
22            _ => unreachable!(),
23        }
24    }
25}
26
27impl<'de> de::Deserializer<'de> for &'_ mut ColorSequence {
28    type Error = Error;
29
30    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
31    where
32        V: Visitor<'de>,
33    {
34        visitor.visit_u32(self.val())
35    }
36
37    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
38    where
39        V: Visitor<'de>,
40    {
41        visitor.visit_seq(self)
42    }
43
44    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
45    where
46        V: Visitor<'de>,
47    {
48        visitor.visit_seq(self)
49    }
50
51    fn deserialize_tuple_struct<V>(
52        self,
53        _name: &'static str,
54        _len: usize,
55        visitor: V,
56    ) -> Result<V::Value, Self::Error>
57    where
58        V: Visitor<'de>,
59    {
60        visitor.visit_seq(self)
61    }
62
63    serde::forward_to_deserialize_any! {
64        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
65        bytes byte_buf option unit unit_struct newtype_struct map struct enum identifier ignored_any
66    }
67}
68
69impl<'de> de::Deserializer<'de> for ColorSequence {
70    type Error = Error;
71
72    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
73    where
74        V: Visitor<'de>,
75    {
76        visitor.visit_u32(self.val())
77    }
78
79    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
80    where
81        V: Visitor<'de>,
82    {
83        visitor.visit_seq(self)
84    }
85
86    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
87    where
88        V: Visitor<'de>,
89    {
90        visitor.visit_seq(self)
91    }
92
93    fn deserialize_tuple_struct<V>(
94        self,
95        _name: &'static str,
96        _len: usize,
97        visitor: V,
98    ) -> Result<V::Value, Self::Error>
99    where
100        V: Visitor<'de>,
101    {
102        visitor.visit_seq(self)
103    }
104
105    serde::forward_to_deserialize_any! {
106        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
107        bytes byte_buf option unit unit_struct newtype_struct map struct enum identifier ignored_any
108    }
109}
110
111impl<'de> SeqAccess<'de> for ColorSequence {
112    type Error = Error;
113
114    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
115    where
116        T: DeserializeSeed<'de>,
117    {
118        if (self.idx >= 3 && self.data.a.is_none()) || (self.idx >= 4 && self.data.a.is_some()) {
119            Ok(None)
120        } else {
121            let result = seed.deserialize(&mut *self);
122            self.idx += 1;
123            result.map(Some)
124        }
125    }
126
127    fn size_hint(&self) -> Option<usize> {
128        let remaining = if self.data.a.is_none() {
129            3 - self.idx
130        } else {
131            4 - self.idx
132        };
133        Some(remaining)
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140    use crate::binary::Rgb;
141    use serde::Deserialize;
142
143    #[test]
144    fn test_color_sequence_rgb_deserialization() {
145        let rgb = Rgb {
146            r: 255,
147            g: 128,
148            b: 64,
149            a: None,
150        };
151        let seq = ColorSequence::new(rgb);
152
153        #[derive(Debug, PartialEq, Deserialize)]
154        struct RgbTuple(u32, u32, u32);
155
156        let result: RgbTuple = RgbTuple::deserialize(seq).unwrap();
157        assert_eq!(result, RgbTuple(255, 128, 64));
158    }
159
160    #[test]
161    fn test_color_sequence_rgba_deserialization() {
162        let rgb = Rgb {
163            r: 255,
164            g: 128,
165            b: 64,
166            a: Some(192),
167        };
168        let seq = ColorSequence::new(rgb);
169
170        #[derive(Debug, PartialEq, Deserialize)]
171        struct RgbaTuple(u32, u32, u32, u32);
172
173        let result: RgbaTuple = RgbaTuple::deserialize(seq).unwrap();
174        assert_eq!(result, RgbaTuple(255, 128, 64, 192));
175    }
176
177    #[test]
178    fn test_color_sequence_sequential_values() {
179        let rgb = Rgb {
180            r: 10,
181            g: 20,
182            b: 30,
183            a: Some(40),
184        };
185        let mut seq = ColorSequence::new(rgb);
186
187        use std::marker::PhantomData;
188
189        let result1 = seq.next_element_seed(PhantomData::<u32>).unwrap().unwrap();
190        assert_eq!(result1, 10);
191
192        let result2 = seq.next_element_seed(PhantomData::<u32>).unwrap().unwrap();
193        assert_eq!(result2, 20);
194
195        let result3 = seq.next_element_seed(PhantomData::<u32>).unwrap().unwrap();
196        assert_eq!(result3, 30);
197
198        let result4 = seq.next_element_seed(PhantomData::<u32>).unwrap().unwrap();
199        assert_eq!(result4, 40);
200    }
201
202    #[test]
203    fn test_color_sequence_size_hint_rgb() {
204        let rgb = Rgb {
205            r: 255,
206            g: 128,
207            b: 64,
208            a: None,
209        };
210        let seq = ColorSequence::new(rgb);
211
212        assert_eq!(seq.size_hint(), Some(3));
213    }
214
215    #[test]
216    fn test_color_sequence_size_hint_rgba() {
217        let rgb = Rgb {
218            r: 255,
219            g: 128,
220            b: 64,
221            a: Some(192),
222        };
223        let seq = ColorSequence::new(rgb);
224
225        assert_eq!(seq.size_hint(), Some(4));
226    }
227
228    #[test]
229    fn test_color_sequence_size_hint_with_progress() {
230        let rgb = Rgb {
231            r: 255,
232            g: 128,
233            b: 64,
234            a: None,
235        };
236        let mut seq = ColorSequence::new(rgb);
237
238        use std::marker::PhantomData;
239
240        seq.next_element_seed(PhantomData::<u32>).unwrap();
241        seq.next_element_seed(PhantomData::<u32>).unwrap();
242
243        assert_eq!(seq.size_hint(), Some(1));
244    }
245
246    #[test]
247    fn test_color_sequence_deserialize_any() {
248        let rgb = Rgb {
249            r: 100,
250            g: 200,
251            b: 50,
252            a: None,
253        };
254        let mut seq = ColorSequence::new(rgb);
255
256        let value: u32 = u32::deserialize(&mut seq).unwrap();
257        assert_eq!(value, 100);
258    }
259}