etherparse/net/
ip_auth_header_slice.rs1use crate::*;
2use core::slice::from_raw_parts;
3
4#[deprecated(
6 since = "0.14.0",
7 note = "Please use the type IpAuthHeaderSlice instead"
8)]
9pub type IpAuthenticationHeaderSlice<'a> = IpAuthHeaderSlice<'a>;
10
11#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13pub struct IpAuthHeaderSlice<'a> {
14 slice: &'a [u8],
15}
16
17impl<'a> IpAuthHeaderSlice<'a> {
18 pub fn from_slice(
20 slice: &'a [u8],
21 ) -> Result<IpAuthHeaderSlice<'a>, err::ip_auth::HeaderSliceError> {
22 use err::ip_auth::{HeaderError::*, HeaderSliceError::*};
23
24 if slice.len() < IpAuthHeader::MIN_LEN {
26 return Err(Len(err::LenError {
27 required_len: IpAuthHeader::MIN_LEN,
28 len: slice.len(),
29 len_source: LenSource::Slice,
30 layer: err::Layer::IpAuthHeader,
31 layer_start_offset: 0,
32 }));
33 }
34
35 let payload_len_enc = unsafe { *slice.get_unchecked(1) };
38
39 if payload_len_enc < 1 {
41 return Err(Content(ZeroPayloadLen));
42 }
43
44 let len = ((payload_len_enc as usize) + 2) * 4;
49 if slice.len() < len {
50 return Err(Len(err::LenError {
51 required_len: len,
52 len: slice.len(),
53 len_source: LenSource::Slice,
54 layer: err::Layer::IpAuthHeader,
55 layer_start_offset: 0,
56 }));
57 }
58
59 Ok(IpAuthHeaderSlice {
61 slice: unsafe { from_raw_parts(slice.as_ptr(), len) },
64 })
65 }
66
67 pub unsafe fn from_slice_unchecked(slice: &'a [u8]) -> IpAuthHeaderSlice<'a> {
79 IpAuthHeaderSlice {
80 slice: from_raw_parts(slice.as_ptr(), ((*slice.get_unchecked(1) as usize) + 2) * 4),
81 }
82 }
83
84 #[inline]
86 pub fn slice(&self) -> &'a [u8] {
87 self.slice
88 }
89
90 #[inline]
94 pub fn next_header(&self) -> IpNumber {
95 IpNumber(unsafe { *self.slice.get_unchecked(0) })
99 }
100
101 #[inline]
103 pub fn spi(&self) -> u32 {
104 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(4)) }
108 }
109
110 #[inline]
113 pub fn sequence_number(&self) -> u32 {
114 unsafe { get_unchecked_be_u32(self.slice.as_ptr().add(8)) }
118 }
119
120 pub fn raw_icv(&self) -> &'a [u8] {
122 &self.slice[12..]
123 }
124
125 pub fn to_header(&self) -> IpAuthHeader {
129 IpAuthHeader::new(
130 self.next_header(),
131 self.spi(),
132 self.sequence_number(),
133 self.raw_icv(),
134 )
135 .unwrap()
136 }
137}
138
139#[cfg(test)]
140mod test {
141 use super::*;
142 use crate::test_gens::*;
143 use alloc::format;
144 use arrayvec::ArrayVec;
145 use err::ip_auth::{HeaderError::*, HeaderSliceError::*};
146 use proptest::prelude::*;
147
148 proptest! {
149 #[test]
150 fn debug(input in ip_auth_any()) {
151 let buffer = input.to_bytes();
152 let slice = IpAuthHeaderSlice::from_slice(&buffer).unwrap();
153 assert_eq!(
154 &format!(
155 "IpAuthHeaderSlice {{ slice: {:?} }}",
156 slice.slice()
157 ),
158 &format!("{:?}", slice)
159 );
160 }
161 }
162
163 #[test]
164 fn clone_eq() {
165 let buffer = IpAuthHeader::new(0.into(), 0, 0, &[0; 4])
166 .unwrap()
167 .to_bytes();
168 let slice = IpAuthHeaderSlice::from_slice(&buffer).unwrap();
169 assert_eq!(slice.clone(), slice);
170 }
171
172 proptest! {
173 #[test]
174 fn from_slice(header in ip_auth_any()) {
175
176 {
178 let mut bytes = ArrayVec::<u8, {IpAuthHeader::MAX_LEN + 2}>::new();
179 bytes.extend(header.to_bytes());
180 bytes.push(1);
181 bytes.push(2);
182
183 let slice = IpAuthHeaderSlice::from_slice(&bytes).unwrap();
184 assert_eq!(slice.slice(), &bytes[..bytes.len() - 2]);
185 }
186
187 {
189 let bytes = header.to_bytes();
190 for len in 0..header.header_len() {
191 assert_eq!(
192 IpAuthHeaderSlice::from_slice(&bytes[..len]).unwrap_err(),
193 Len(err::LenError{
194 required_len: if len < IpAuthHeader::MIN_LEN {
195 IpAuthHeader::MIN_LEN
196 } else {
197 header.header_len()
198 },
199 len: len,
200 len_source: LenSource::Slice,
201 layer: err::Layer::IpAuthHeader,
202 layer_start_offset: 0,
203 })
204 );
205 }
206 }
207
208 {
210 let mut bytes = header.to_bytes();
211 bytes[1] = 0;
213 assert_eq!(
214 IpAuthHeaderSlice::from_slice(&bytes).unwrap_err(),
215 Content(ZeroPayloadLen)
216 );
217 }
218 }
219 }
220
221 proptest! {
222 #[test]
223 fn from_slice_unchecked(header in ip_auth_any()) {
224 let bytes = header.to_bytes();
225 let slice = unsafe {
226 IpAuthHeaderSlice::from_slice_unchecked(&bytes)
227 };
228 assert_eq!(slice.slice(), &bytes[..]);
229 }
230 }
231
232 proptest! {
233 #[test]
234 fn getters(header in ip_auth_any()) {
235 let bytes = header.to_bytes();
236 let slice = IpAuthHeaderSlice::from_slice(&bytes).unwrap();
237 assert_eq!(slice.slice(), &bytes[..]);
238 assert_eq!(slice.next_header(), header.next_header);
239 assert_eq!(slice.spi(), header.spi);
240 assert_eq!(slice.sequence_number(), header.sequence_number);
241 assert_eq!(slice.raw_icv(), header.raw_icv());
242 }
243 }
244
245 proptest! {
246 #[test]
247 fn to_header(header in ip_auth_any()) {
248 let bytes = header.to_bytes();
249 assert_eq!(
250 header,
251 IpAuthHeaderSlice::from_slice(&bytes)
252 .unwrap()
253 .to_header()
254 );
255 }
256 }
257}