fusio_log/serdes/
option.rs

1use fusio::{Error, SeqRead, Write};
2
3use super::{Decode, Encode};
4
5impl<V> Encode for Option<V>
6where
7    V: Encode + Sync,
8{
9    async fn encode<W>(&self, writer: &mut W) -> Result<(), Error>
10    where
11        W: Write,
12    {
13        match self {
14            None => 0u8.encode(writer).await?,
15            Some(v) => {
16                1u8.encode(writer).await?;
17                v.encode(writer).await?;
18            }
19        }
20        Ok(())
21    }
22
23    fn size(&self) -> usize {
24        match self {
25            None => 1,
26            Some(v) => 1 + v.size(),
27        }
28    }
29}
30
31impl<V> Decode for Option<V>
32where
33    V: Decode,
34{
35    async fn decode<R: SeqRead>(reader: &mut R) -> Result<Self, Error> {
36        match u8::decode(reader).await? {
37            0 => Ok(None),
38            1 => Ok(Some(V::decode(reader).await?)),
39            _ => panic!("invalid option tag"),
40        }
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use std::io::Cursor;
47
48    use tokio::io::AsyncSeekExt;
49
50    use crate::serdes::{Decode, Encode};
51
52    #[tokio::test]
53    async fn test_encode_decode() {
54        let source_0 = Some(1u64);
55        let source_1 = None;
56        let source_2 = Some("Hello! Tonbo".to_string());
57
58        let mut bytes = Vec::new();
59        let mut cursor = Cursor::new(&mut bytes);
60
61        source_0.encode(&mut cursor).await.unwrap();
62        source_1.encode(&mut cursor).await.unwrap();
63        source_2.encode(&mut cursor).await.unwrap();
64
65        cursor.seek(std::io::SeekFrom::Start(0)).await.unwrap();
66        let decoded_0 = Option::<u64>::decode(&mut cursor).await.unwrap();
67        let decoded_1 = Option::<u64>::decode(&mut cursor).await.unwrap();
68        let decoded_2 = Option::<String>::decode(&mut cursor).await.unwrap();
69
70        assert_eq!(source_0, decoded_0);
71        assert_eq!(source_1, decoded_1);
72        assert_eq!(source_2, decoded_2);
73    }
74}