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