plabble_codec/codec/common/
slot_range.rs

1use crate::abstractions::{Serializable, SerializationError, SerializationInfo};
2
3/// A range of slots.
4///
5/// # Fields
6///
7/// * `from` - The first slot in the range. If `None`, the range starts at the first slot.
8/// * `to` - The last slot in the range. If `None`, the range ends at the last slot.
9#[derive(Debug, PartialEq, Eq)]
10pub struct SlotRange {
11    pub from: Option<u16>,
12    pub to: Option<u16>,
13}
14
15impl SlotRange {
16    /// Creates a new slot range with no start and no end.
17    pub fn empty() -> Self {
18        Self {
19            from: None,
20            to: None,
21        }
22    }
23}
24
25impl Serializable for SlotRange {
26    fn size(&self) -> usize {
27        let size = if self.from.is_some() { 2 } else { 0 } + if self.to.is_some() { 2 } else { 0 };
28        size as usize
29    }
30
31    fn get_bytes(&self) -> Vec<u8> {
32        let mut buff = Vec::new();
33        if let Some(from) = self.from {
34            buff.extend_from_slice(&from.to_be_bytes());
35            if let Some(to) = self.to {
36                buff.extend_from_slice(&to.to_be_bytes());
37            }
38        }
39
40        buff
41    }
42
43    fn from_bytes(data: &[u8], _: Option<SerializationInfo>) -> Result<Self, SerializationError>
44    where
45        Self: Sized,
46    {
47        if data.is_empty() {
48            Ok(Self {
49                from: None,
50                to: None,
51            })
52        } else if data.len() % 2 != 0 {
53            Err(SerializationError::TooFewBytes(1))
54        } else {
55            let mut from = [0u8; 2];
56            from.copy_from_slice(&data[..2]);
57            let from = Some(u16::from_be_bytes(from));
58            Ok(Self {
59                from,
60                to: if data.len() > 2 {
61                    let mut to = [0u8; 2];
62                    to.copy_from_slice(&data[2..4]);
63                    Some(u16::from_be_bytes(to))
64                } else {
65                    None
66                },
67            })
68        }
69    }
70}
71
72#[cfg(test)]
73mod test {
74    use super::*;
75
76    #[test]
77    fn can_serialize_0_slots() {
78        let range = SlotRange::empty();
79        assert_eq!(Vec::<u8>::new(), range.get_bytes());
80    }
81
82    #[test]
83    fn can_serialize_1_slot() {
84        let range = SlotRange {
85            from: Some(257),
86            to: None,
87        };
88        assert_eq!(vec![1, 1], range.get_bytes());
89    }
90
91    #[test]
92    fn can_serialize_2_slots() {
93        let range = SlotRange {
94            from: Some(258),
95            to: Some(259),
96        };
97        assert_eq!(vec![1, 2, 1, 3], range.get_bytes());
98    }
99
100    #[test]
101    fn can_parse_0_slots() {
102        let bytes = &[];
103        let range = SlotRange::from_bytes(bytes, None).unwrap();
104        assert_eq!(
105            SlotRange {
106                from: None,
107                to: None
108            },
109            range
110        );
111    }
112
113    #[test]
114    fn can_parse_1_slot() {
115        let bytes = &[0, 255];
116        let range = SlotRange::from_bytes(bytes, None).unwrap();
117        assert_eq!(
118            SlotRange {
119                from: Some(255),
120                to: None
121            },
122            range
123        );
124    }
125
126    #[test]
127    fn can_parse_2_slots() {
128        let bytes = &[255, 255, 255, 254];
129        let range = SlotRange::from_bytes(bytes, None).unwrap();
130        assert_eq!(
131            SlotRange {
132                from: Some(u16::MAX),
133                to: Some(u16::MAX - 1)
134            },
135            range
136        );
137    }
138}