ytls_util/
byte_slices.rs

1//! Byte Slices handling
2
3/// Non-continuous borrowed byte slices. Final destination
4/// will typically copy into continuous "worst case" slice once.
5pub enum ByteSlices<'r> {
6    /// Single continuous slice
7    Single(&'r [u8]),
8    /// Non-continuous Double of continuous slices
9    Double(&'r [u8], &'r [u8]),
10    /// Non-continuos Triple of continuous slices
11    Triple(&'r [u8], &'r [u8], &'r [u8]),
12}
13
14impl<'r> ByteSlices<'r> {
15    /// Len of the slices
16    #[inline]
17    pub fn len(&'r self) -> usize {
18        match self {
19            Self::Single(_) => 1,
20            Self::Double(_, _) => 2,
21            Self::Triple(_, _, _) => 3,
22        }
23    }
24    /// Total len of all the slices combined
25    #[inline]
26    pub fn total_len(&'r self) -> usize {
27        match self {
28            Self::Single(x) => x.len(),
29            Self::Double(x, y) => x.len() + y.len(),
30            Self::Triple(x, y, z) => x.len() + y.len() + z.len(),
31        }
32    }
33    /// Iter
34    #[inline]
35    pub fn iter(&'r self) -> ByteSlicesIter<'r> {
36        ByteSlicesIter { b: self, cur: 0 }
37    }
38}
39
40pub struct ByteSlicesIter<'r> {
41    cur: usize,
42    b: &'r ByteSlices<'r>,
43}
44
45impl<'r> Iterator for ByteSlicesIter<'r> {
46    type Item = &'r [u8];
47    fn next(&mut self) -> Option<Self::Item> {
48        let r = match self.b {
49            ByteSlices::Single(x) => match self.cur {
50                0 => Some(x),
51                _ => None,
52            },
53            ByteSlices::Double(x, y) => match self.cur {
54                0 => Some(x),
55                1 => Some(y),
56                _ => None,
57            },
58            ByteSlices::Triple(x, y, z) => match self.cur {
59                0 => Some(x),
60                1 => Some(y),
61                2 => Some(z),
62                _ => None,
63            },
64        };
65        if r.is_some() {
66            self.cur += 1;
67        };
68        r.map(|v| &**v)
69    }
70}
71
72#[cfg(test)]
73mod test {
74    use super::*;
75
76    #[test]
77    fn single() {
78        let x: [u8; 2] = [42, 69];
79        let bs = ByteSlices::Single(&x);
80        assert_eq!(bs.len(), 1);
81        assert_eq!(bs.total_len(), 2);
82    }
83
84    #[test]
85    fn single_iter() {
86        let x: [u8; 2] = [42, 69];
87        let bs = ByteSlices::Single(&x);
88        let mut i = bs.iter();
89        assert_eq!(i.next(), Some(x.as_ref()));
90        assert_eq!(i.next(), None);
91    }
92
93    #[test]
94    fn double() {
95        let x: [u8; 2] = [42, 69];
96        let y: [u8; 2] = [70, 71];
97        let bs = ByteSlices::Double(&x, &y);
98        assert_eq!(bs.len(), 2);
99        assert_eq!(bs.total_len(), 4);
100    }
101
102    #[test]
103    fn double_iter() {
104        let x: [u8; 2] = [42, 69];
105        let y: [u8; 2] = [70, 71];
106        let bs = ByteSlices::Double(&x, &y);
107        let mut i = bs.iter();
108        assert_eq!(i.next(), Some(x.as_ref()));
109        assert_eq!(i.next(), Some(y.as_ref()));
110        assert_eq!(i.next(), None);
111    }
112
113    #[test]
114    fn triple() {
115        let x: [u8; 2] = [42, 69];
116        let y: [u8; 2] = [70, 71];
117        let z: [u8; 2] = [72, 73];
118        let bs = ByteSlices::Triple(&x, &y, &z);
119        assert_eq!(bs.len(), 3);
120        assert_eq!(bs.total_len(), 6);
121    }
122
123    #[test]
124    fn triple_iter() {
125        let x: [u8; 2] = [42, 69];
126        let y: [u8; 2] = [70, 71];
127        let z: [u8; 2] = [72, 73];
128        let bs = ByteSlices::Triple(&x, &y, &z);
129        let mut i = bs.iter();
130
131        assert_eq!(i.next(), Some(x.as_ref()));
132        assert_eq!(i.next(), Some(y.as_ref()));
133        assert_eq!(i.next(), Some(z.as_ref()));
134        assert_eq!(i.next(), None);
135    }
136}