1 | //! Helpers for the generated code |
2 | |
3 | use super::x11_utils::TryParse; |
4 | use core::marker::PhantomData; |
5 | |
6 | /// Iterator implementation used by [GetPropertyReply]. |
7 | /// |
8 | /// This is the actual type returned by [GetPropertyReply::value8], [GetPropertyReply::value16], |
9 | /// and [GetPropertyReply::value32]. This type needs to be public due to Rust's visibility rules. |
10 | /// |
11 | /// [GetPropertyReply]: crate::protocol::xproto::GetPropertyReply |
12 | /// [GetPropertyReply::value8]: crate::protocol::xproto::GetPropertyReply::value8 |
13 | /// [GetPropertyReply::value16]: crate::protocol::xproto::GetPropertyReply::value16 |
14 | /// [GetPropertyReply::value32]: crate::protocol::xproto::GetPropertyReply::value32 |
15 | #[derive (Debug, Clone)] |
16 | pub struct PropertyIterator<'a, T>(&'a [u8], PhantomData<T>); |
17 | |
18 | impl<'a, T> PropertyIterator<'a, T> { |
19 | pub(crate) fn new(value: &'a [u8]) -> Self { |
20 | PropertyIterator(value, PhantomData) |
21 | } |
22 | } |
23 | |
24 | impl<T> Iterator for PropertyIterator<'_, T> |
25 | where |
26 | T: TryParse, |
27 | { |
28 | type Item = T; |
29 | |
30 | fn next(&mut self) -> Option<Self::Item> { |
31 | match T::try_parse(self.0) { |
32 | Ok((value: T, remaining: &[u8])) => { |
33 | self.0 = remaining; |
34 | Some(value) |
35 | } |
36 | Err(_) => { |
37 | self.0 = &[]; |
38 | None |
39 | } |
40 | } |
41 | } |
42 | |
43 | fn size_hint(&self) -> (usize, Option<usize>) { |
44 | let size: usize = self.0.len() / core::mem::size_of::<T>(); |
45 | (size, Some(size)) |
46 | } |
47 | } |
48 | |
49 | impl<T: TryParse> core::iter::FusedIterator for PropertyIterator<'_, T> {} |
50 | |
51 | #[cfg (test)] |
52 | mod tests { |
53 | use super::PropertyIterator; |
54 | use alloc::vec::Vec; |
55 | |
56 | #[test ] |
57 | fn test_parse_u8() { |
58 | let input = [0u8, 1, 2, 3, 4, 5]; |
59 | let output = PropertyIterator::new(&input).collect::<Vec<u8>>(); |
60 | assert_eq!(&input[..], output); |
61 | } |
62 | |
63 | #[test ] |
64 | fn test_parse_u32() { |
65 | let expected = [0u32, 1, 2, 3, 4, 5]; |
66 | let input = { |
67 | let mut input = Vec::new(); |
68 | for value in &expected { |
69 | input.extend_from_slice(&value.to_ne_bytes()); |
70 | } |
71 | input |
72 | }; |
73 | |
74 | let output = PropertyIterator::new(&input).collect::<Vec<u32>>(); |
75 | assert_eq!(&expected[..], output); |
76 | } |
77 | |
78 | #[test ] |
79 | fn test_size_hint() { |
80 | let hint = PropertyIterator::<u32>::new(&[0; 0]).size_hint(); |
81 | assert_eq!(hint, (0, Some(0))); |
82 | |
83 | let hint = PropertyIterator::<u32>::new(&[0; 8]).size_hint(); |
84 | assert_eq!(hint, (2, Some(2))); |
85 | |
86 | // In this case, the data is not an exact multiple of the element size |
87 | let hint = PropertyIterator::<u32>::new(&[0; 30]).size_hint(); |
88 | assert_eq!(hint, (7, Some(7))); |
89 | } |
90 | } |
91 | |