fusio_log/serdes/
option.rs1use 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}