etherparse/link/
ethernet2_header_slice.rs1use crate::*;
2use core::slice::from_raw_parts;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct Ethernet2HeaderSlice<'a> {
7 pub(crate) slice: &'a [u8],
8}
9
10impl<'a> Ethernet2HeaderSlice<'a> {
11 pub fn from_slice(slice: &'a [u8]) -> Result<Ethernet2HeaderSlice<'a>, err::LenError> {
13 if slice.len() < Ethernet2Header::LEN {
15 return Err(err::LenError {
16 required_len: Ethernet2Header::LEN,
17 len: slice.len(),
18 len_source: LenSource::Slice,
19 layer: err::Layer::Ethernet2Header,
20 layer_start_offset: 0,
21 });
22 }
23
24 Ok(Ethernet2HeaderSlice {
26 slice: unsafe { from_raw_parts(slice.as_ptr(), Ethernet2Header::LEN) },
30 })
31 }
32
33 #[inline]
45 #[cfg(feature = "std")]
46 pub(crate) unsafe fn from_slice_unchecked(slice: &[u8]) -> Ethernet2HeaderSlice {
47 debug_assert!(slice.len() == Ethernet2Header::LEN);
48 Ethernet2HeaderSlice { slice }
49 }
50
51 #[inline]
53 pub fn slice(&self) -> &'a [u8] {
54 self.slice
55 }
56
57 #[inline]
59 pub fn destination(&self) -> [u8; 6] {
60 unsafe { get_unchecked_6_byte_array(self.slice.as_ptr()) }
64 }
65
66 #[inline]
68 pub fn source(&self) -> [u8; 6] {
69 unsafe { get_unchecked_6_byte_array(self.slice.as_ptr().add(6)) }
73 }
74
75 #[inline]
78 pub fn ether_type(&self) -> EtherType {
79 EtherType(unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(12)) })
83 }
84
85 pub fn to_header(&self) -> Ethernet2Header {
87 Ethernet2Header {
88 source: self.source(),
89 destination: self.destination(),
90 ether_type: self.ether_type(),
91 }
92 }
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98 use crate::test_gens::*;
99 use alloc::{format, vec::Vec};
100 use proptest::prelude::*;
101
102 proptest! {
103 #[test]
104 fn from_slice(
105 input in ethernet_2_any(),
106 dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
107 ) {
108 let mut buffer: Vec<u8> = Vec::with_capacity(14 + dummy_data.len());
110 input.write(&mut buffer).unwrap();
111 buffer.extend(&dummy_data[..]);
112
113 {
115 let result = Ethernet2HeaderSlice::from_slice(&buffer[..]).unwrap();
116 assert_eq!(&buffer[..14], result.slice());
117 }
118
119 for len in 0..=13 {
121 assert_eq!(
122 Ethernet2HeaderSlice::from_slice(&buffer[..len]),
123 Err(err::LenError{
124 required_len: Ethernet2Header::LEN,
125 len: len,
126 len_source: LenSource::Slice,
127 layer: err::Layer::Ethernet2Header,
128 layer_start_offset: 0,
129 })
130 );
131 }
132 }
133 }
134
135 proptest! {
136 #[test]
137 fn getters(input in ethernet_2_any()) {
138 let buffer = input.to_bytes();
139 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap();
140 assert_eq!(input.destination, slice.destination());
141 assert_eq!(input.source, slice.source());
142 assert_eq!(input.ether_type, slice.ether_type());
143 }
144 }
145
146 proptest! {
147 #[test]
148 fn to_header(input in ethernet_2_any()) {
149 let buffer = input.to_bytes();
150 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap();
151 assert_eq!(input, slice.to_header());
152 }
153 }
154
155 proptest! {
156 #[test]
157 fn clone_eq(input in ethernet_2_any()) {
158 let buffer = input.to_bytes();
159 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap();
160 assert_eq!(slice, slice.clone());
161 }
162 }
163
164 proptest! {
165 #[test]
166 fn dbg(input in ethernet_2_any()) {
167 let buffer = input.to_bytes();
168 let slice = Ethernet2HeaderSlice::from_slice(&buffer).unwrap();
169 assert_eq!(
170 &format!(
171 "Ethernet2HeaderSlice {{ slice: {:?} }}",
172 slice.slice()
173 ),
174 &format!("{:?}", slice)
175 );
176 }
177 }
178}