etherparse/net/
ipv6_ext_slice_iter.rs1use crate::*;
2use core::slice::from_raw_parts;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct Ipv6ExtensionSliceIter<'a> {
7 pub(crate) next_header: IpNumber,
8 pub(crate) rest: &'a [u8],
9}
10
11impl Default for Ipv6ExtensionSliceIter<'_> {
12 fn default() -> Self {
13 Ipv6ExtensionSliceIter {
14 next_header: IpNumber::IPV6_NO_NEXT_HEADER,
17 rest: &[],
18 }
19 }
20}
21
22impl<'a> Iterator for Ipv6ExtensionSliceIter<'a> {
23 type Item = Ipv6ExtensionSlice<'a>;
24
25 fn next(&mut self) -> Option<Ipv6ExtensionSlice<'a>> {
26 use ip_number::*;
27 use Ipv6ExtensionSlice::*;
28
29 match self.next_header {
30 IPV6_HOP_BY_HOP => unsafe {
36 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest);
37 let len = slice.slice().len();
38 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len);
39 self.next_header = slice.next_header();
40 Some(HopByHop(slice))
41 },
42 IPV6_ROUTE => unsafe {
43 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest);
44 let len = slice.slice().len();
45 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len);
46 self.next_header = slice.next_header();
47 Some(Routing(slice))
48 },
49 IPV6_DEST_OPTIONS => unsafe {
50 let slice = Ipv6RawExtHeaderSlice::from_slice_unchecked(self.rest);
51 let len = slice.slice().len();
52 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len);
53 self.next_header = slice.next_header();
54 Some(DestinationOptions(slice))
55 },
56 IPV6_FRAG => unsafe {
57 let slice = Ipv6FragmentHeaderSlice::from_slice_unchecked(self.rest);
58 let len = slice.slice().len();
59 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len);
60 self.next_header = slice.next_header();
61
62 Some(Fragment(slice))
63 },
64 AUTH => unsafe {
65 let slice = IpAuthHeaderSlice::from_slice_unchecked(self.rest);
66 let len = slice.slice().len();
67 self.rest = from_raw_parts(self.rest.as_ptr().add(len), self.rest.len() - len);
68 self.next_header = slice.next_header();
69 Some(Authentication(slice))
70 },
71 _ => None,
73 }
74 }
75}
76
77#[cfg(test)]
78mod test {
79 use super::ipv6_exts_test_helpers::*;
80 use super::*;
81 use crate::ip_number::*;
82 use crate::test_gens::*;
83 use alloc::borrow::ToOwned;
84 use proptest::prelude::*;
85
86 #[test]
87 fn into_iter() {
88 let a: Ipv6ExtensionsSlice = Default::default();
89 let mut iter = a.into_iter();
90 assert_eq!(None, iter.next());
91 }
92
93 proptest! {
94 #[test]
95 fn next(
96 header_size in any::<u8>(),
97 post_header in ip_number_any()
98 .prop_filter("Must be a non ipv6 header relevant ip number".to_owned(),
99 |v| !EXTENSION_KNOWN_IP_NUMBERS.iter().any(|&x| v == &x)
100 )
101 ) {
102 fn run_test(ip_numbers: &[IpNumber], header_sizes: &[u8]) {
104 let e = ExtensionTestPayload::new(
106 ip_numbers,
107 header_sizes
108 );
109
110 if false == e.ip_numbers[1..].iter().any(|&x| x == IPV6_HOP_BY_HOP) {
112 let (header, _, _) = Ipv6ExtensionsSlice::from_slice(ip_numbers[0], e.slice()).unwrap();
114 let mut iter = header.into_iter();
115 let mut slice = e.slice();
116
117 for i in 0..e.ip_numbers.len() - 1 {
119 use Ipv6ExtensionSlice::*;
120
121 let next = iter.next().unwrap();
123 match e.ip_numbers[i] {
124 IPV6_HOP_BY_HOP => {
125 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap();
126 assert_eq!(next, HopByHop(header.clone()));
127 slice = &slice[header.slice().len()..];
128 },
129 IPV6_ROUTE => {
130 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap();
131 assert_eq!(next, Routing(header.clone()));
132 slice = &slice[header.slice().len()..];
133 },
134 IPV6_DEST_OPTIONS => {
135 let header = Ipv6RawExtHeaderSlice::from_slice(slice).unwrap();
136 assert_eq!(next, DestinationOptions(header.clone()));
137 slice = &slice[header.slice().len()..];
138 }
139 IPV6_FRAG => {
140 let header = Ipv6FragmentHeaderSlice::from_slice(slice).unwrap();
141 assert_eq!(next, Fragment(header.clone()));
142 slice = &slice[header.slice().len()..];
143 },
144 AUTH => {
145 let header = IpAuthHeaderSlice::from_slice(slice).unwrap();
146 assert_eq!(next, Authentication(header.clone()));
147 slice = &slice[header.slice().len()..];
148 },
149 _ => unreachable!()
150 }
151 }
152
153 assert_eq!(None, iter.next());
155 }
156 }
157
158 for first_header in &EXTENSION_KNOWN_IP_NUMBERS {
160
161 run_test(
163 &[*first_header, post_header],
164 &[header_size],
165 );
166
167 for second_header in &EXTENSION_KNOWN_IP_NUMBERS {
168
169 run_test(
171 &[*first_header, *second_header, post_header],
172 &[header_size],
173 );
174
175 for third_header in &EXTENSION_KNOWN_IP_NUMBERS {
176 run_test(
178 &[*first_header, *second_header, *third_header, post_header],
179 &[header_size],
180 );
181 }
182 }
183 }
184 }
185 }
186
187 #[test]
188 fn debug() {
189 use alloc::format;
190
191 let a: Ipv6ExtensionSliceIter = Default::default();
192 assert_eq!(
193 format!(
194 "Ipv6ExtensionSliceIter {{ next_header: {:?}, rest: [] }}",
195 IpNumber(59)
196 ),
197 format!("{:?}", a)
198 );
199 }
200
201 #[test]
202 fn clone_eq() {
203 let a: Ipv6ExtensionSliceIter = Default::default();
204 assert_eq!(a.clone(), a);
205 }
206
207 #[test]
208 fn default() {
209 let mut a: Ipv6ExtensionSliceIter = Default::default();
210 assert_eq!(None, a.next());
211 }
212}