1mod headers;
4pub use headers::*;
5
6mod payloads;
7pub use payloads::*;
8
9mod nested;
10pub use nested::*;
11
12use super::{Error, Result};
13
14pub struct InformationElements<T: AsRef<[u8]>> {
16 data: T,
17}
18
19impl<T: AsRef<[u8]>> InformationElements<T> {
20 pub fn new(data: T) -> Result<Self> {
27 let ie = Self::new_unchecked(data);
28
29 if !ie.check_len() {
30 return Err(Error);
31 }
32
33 Ok(ie)
34 }
35
36 fn check_len(&self) -> bool {
39 let mut len = 0;
40
41 let mut iter = self.header_information_elements();
42 while iter.next().is_some() {}
43 len += iter.offset();
44
45 if len > self.data.as_ref().len() {
46 return false;
47 }
48
49 let mut iter = self.payload_information_elements();
50 while iter.next().is_some() {}
51 len += iter.offset();
52
53 self.data.as_ref().len() >= len
54 }
55
56 pub fn new_unchecked(data: T) -> Self {
59 Self { data }
60 }
61
62 #[allow(clippy::len_without_is_empty)]
64 pub fn len(&self) -> usize {
65 let mut len = 0;
66
67 let mut iter = self.header_information_elements();
68 while iter.next().is_some() {}
69 len += iter.offset();
70
71 let mut iter = self.payload_information_elements();
72 while iter.next().is_some() {}
73 len += iter.offset();
74
75 len
76 }
77
78 pub fn header_information_elements(&self) -> HeaderInformationElementsIterator {
80 HeaderInformationElementsIterator {
81 data: self.data.as_ref(),
82 offset: 0,
83 terminated: self.data.as_ref().is_empty(),
84 }
85 }
86
87 pub fn payload_information_elements(&self) -> PayloadInformationElementsIterator {
89 let start = self
90 .header_information_elements()
91 .map(|ie| ie.len() + 2)
92 .sum::<usize>();
93
94 let terminated = start >= self.data.as_ref().len();
95
96 PayloadInformationElementsIterator {
97 data: &self.data.as_ref()[start..],
98 offset: 0,
99 terminated,
100 }
101 }
102}