multiboot2_common/
iter.rs1use crate::{increase_to_alignment, DynSizedStructure, Header, ALIGNMENT};
6use core::marker::PhantomData;
7use core::mem;
8
9#[derive(Clone, Debug)]
21pub struct TagIter<'a, H: Header> {
22 next_tag_offset: usize,
24 buffer: &'a [u8],
25 _t: PhantomData<H>,
28}
29
30impl<'a, H: Header> TagIter<'a, H> {
31 #[must_use]
33 pub fn new(mem: &'a [u8]) -> Self {
34 assert_eq!(mem.as_ptr().align_offset(ALIGNMENT), 0);
36
37 TagIter {
38 next_tag_offset: 0,
39 buffer: mem,
40 _t: PhantomData,
41 }
42 }
43}
44
45impl<'a, H: Header + 'a> Iterator for TagIter<'a, H> {
46 type Item = &'a DynSizedStructure<H>;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 if self.next_tag_offset == self.buffer.len() {
50 return None;
51 }
52 assert!(self.next_tag_offset < self.buffer.len());
53
54 let ptr = unsafe { self.buffer.as_ptr().add(self.next_tag_offset) }.cast::<H>();
55 let tag_hdr = unsafe { &*ptr };
56
57 let slice = {
61 let from = self.next_tag_offset;
62 let len = mem::size_of::<H>() + tag_hdr.payload_len();
63 let to = from + len;
64
65 let to = increase_to_alignment(to);
69
70 self.next_tag_offset += to - from;
72
73 &self.buffer[from..to]
74 };
75
76 let tag = DynSizedStructure::ref_from_slice(slice).unwrap();
78 Some(tag)
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use crate::test_utils::{AlignedBytes, DummyTestHeader};
85 use crate::TagIter;
86 use core::borrow::Borrow;
87
88 #[test]
89 fn test_tag_iter() {
90 #[rustfmt::skip]
91 let bytes = AlignedBytes::new(
92 [
93 0xff, 0, 0, 0,
95 8, 0, 0, 0,
96 0xfe, 0, 0, 0,
98 12, 0, 0, 0,
99 1, 2, 3, 4,
100 0, 0, 0, 0,
102 0, 0, 0, 0,
104 8, 0, 0, 0,
105 ],
106 );
107 let mut iter = TagIter::<DummyTestHeader>::new(bytes.borrow());
108 let first = iter.next().unwrap();
109 assert_eq!(first.header().typ(), 0xff);
110 assert_eq!(first.header().size(), 8);
111 assert!(first.payload().is_empty());
112
113 let second = iter.next().unwrap();
114 assert_eq!(second.header().typ(), 0xfe);
115 assert_eq!(second.header().size(), 12);
116 assert_eq!(&second.payload(), &[1, 2, 3, 4]);
117
118 let third = iter.next().unwrap();
119 assert_eq!(third.header().typ(), 0);
120 assert_eq!(third.header().size(), 8);
121 assert!(first.payload().is_empty());
122
123 assert_eq!(iter.next(), None);
124 }
125}