etherparse/net/
ipv6_raw_ext_header_slice.rs1use crate::*;
2use core::slice::from_raw_parts;
3
4#[deprecated(
6 since = "0.14.0",
7 note = "Please use the type Ipv6RawExtHeaderSlice instead"
8)]
9pub type Ipv6RawExtensionHeaderSlice<'a> = Ipv6RawExtHeaderSlice<'a>;
10
11#[derive(Clone, Debug, Eq, PartialEq)]
26pub struct Ipv6RawExtHeaderSlice<'a> {
27 slice: &'a [u8],
29}
30
31impl<'a> Ipv6RawExtHeaderSlice<'a> {
32 pub fn header_type_supported(next_header: IpNumber) -> bool {
34 Ipv6RawExtHeader::header_type_supported(next_header)
35 }
36
37 pub fn from_slice(slice: &'a [u8]) -> Result<Ipv6RawExtHeaderSlice<'a>, err::LenError> {
39 if slice.len() < 8 {
41 return Err(err::LenError {
42 required_len: 8,
43 len: slice.len(),
44 len_source: LenSource::Slice,
45 layer: err::Layer::Ipv6ExtHeader,
46 layer_start_offset: 0,
47 });
48 }
49
50 let len = ((slice[1] as usize) + 1) * 8;
52
53 if slice.len() < len {
55 return Err(err::LenError {
56 required_len: len,
57 len: slice.len(),
58 len_source: LenSource::Slice,
59 layer: err::Layer::Ipv6ExtHeader,
60 layer_start_offset: 0,
61 });
62 }
63
64 Ok(Ipv6RawExtHeaderSlice {
66 slice: unsafe { from_raw_parts(slice.as_ptr(), len) },
70 })
71 }
72
73 pub unsafe fn from_slice_unchecked(slice: &'a [u8]) -> Ipv6RawExtHeaderSlice<'a> {
86 Ipv6RawExtHeaderSlice {
87 slice: from_raw_parts(slice.as_ptr(), ((*slice.get_unchecked(1) as usize) + 1) * 8),
88 }
89 }
90
91 #[inline]
93 pub fn slice(&self) -> &'a [u8] {
94 self.slice
95 }
96
97 #[inline]
101 pub fn next_header(&self) -> IpNumber {
102 IpNumber(unsafe { *self.slice.get_unchecked(0) })
103 }
104
105 #[inline]
111 pub fn payload(&self) -> &'a [u8] {
112 unsafe { from_raw_parts(self.slice.as_ptr().add(2), self.slice.len() - 2) }
113 }
114
115 pub fn to_header(&self) -> Ipv6RawExtHeader {
121 Ipv6RawExtHeader::new_raw(self.next_header(), self.payload()).unwrap()
122 }
123}
124
125#[cfg(test)]
126mod test {
127 use crate::{test_gens::*, *};
128 use alloc::{format, vec::Vec};
129 use proptest::prelude::*;
130
131 proptest! {
132 #[test]
133 fn debug(header in ipv6_raw_ext_any()) {
134 let bytes = header.to_bytes();
135 let slice = Ipv6RawExtHeaderSlice::from_slice(&bytes).unwrap();
136 assert_eq!(
137 format!("{:?}", slice),
138 format!("Ipv6RawExtHeaderSlice {{ slice: {:?} }}", slice.slice())
139 );
140 }
141 }
142
143 proptest! {
144 #[test]
145 fn clone_eq(header in ipv6_raw_ext_any()) {
146 let bytes = header.to_bytes();
147 let slice = Ipv6RawExtHeaderSlice::from_slice(&bytes).unwrap();
148 assert_eq!(slice.clone(), slice);
149 }
150 }
151
152 #[test]
153 fn header_type_supported() {
154 use ip_number::*;
155 for value in 0..=u8::MAX {
156 let expected_supported = match IpNumber(value) {
157 IPV6_HOP_BY_HOP | IPV6_DEST_OPTIONS | IPV6_ROUTE | MOBILITY | HIP | SHIM6 => true,
158 _ => false,
159 };
160 assert_eq!(
161 expected_supported,
162 Ipv6RawExtHeaderSlice::header_type_supported(IpNumber(value))
163 );
164 }
165 }
166
167 proptest! {
168 #[test]
169 fn from_slice(header in ipv6_raw_ext_any()) {
170 {
172 let mut bytes = Vec::with_capacity(header.header_len() + 2);
173 bytes.extend_from_slice(&header.to_bytes());
174 bytes.push(1);
175 bytes.push(2);
176
177 let (actual_header, actual_rest) = Ipv6RawExtHeader::from_slice(&bytes).unwrap();
178 assert_eq!(actual_header, header);
179 assert_eq!(actual_rest, &[1, 2]);
180 }
181
182 {
184 let bytes = header.to_bytes();
185 for len in 0..bytes.len() {
186 assert_eq!(
187 Ipv6RawExtHeader::from_slice(&bytes[..len]).unwrap_err(),
188 err::LenError{
189 required_len: if len < Ipv6RawExtHeader::MIN_LEN {
190 Ipv6RawExtHeader::MIN_LEN
191 } else {
192 header.header_len()
193 },
194 len: len,
195 len_source: LenSource::Slice,
196 layer: err::Layer::Ipv6ExtHeader,
197 layer_start_offset: 0,
198 }
199 );
200 }
201 }
202 }
203 }
204
205 proptest! {
206 #[test]
207 fn from_slice_unchecked(header in ipv6_raw_ext_any()) {
208 let bytes = header.to_bytes();
209 let slice = unsafe {
210 Ipv6RawExtHeaderSlice::from_slice_unchecked(&bytes)
211 };
212 assert_eq!(&bytes[..], slice.slice());
213 }
214 }
215
216 proptest! {
217 #[test]
218 fn getters(header in ipv6_raw_ext_any()) {
219 let bytes = header.to_bytes();
220 let slice = Ipv6RawExtHeaderSlice::from_slice(&bytes).unwrap();
221 assert_eq!(slice.next_header(), header.next_header);
222 assert_eq!(slice.payload(), header.payload());
223 }
224 }
225
226 proptest! {
227 #[test]
228 fn to_header(header in ipv6_raw_ext_any()) {
229 let bytes = header.to_bytes();
230 let slice = Ipv6RawExtHeaderSlice::from_slice(&bytes).unwrap();
231 assert_eq!(header, slice.to_header());
232 }
233 }
234}