1use crate::{err::Layer, err::SliceWriteSpaceError, *};
2
3#[derive(Clone, Debug, Eq, PartialEq, Default)]
5pub struct Ethernet2Header {
6 pub source: [u8; 6],
8 pub destination: [u8; 6],
10 pub ether_type: EtherType,
12}
13
14impl Ethernet2Header {
15 pub const LEN: usize = 14;
17
18 #[deprecated(since = "0.14.0", note = "Use `Ethernet2Header::LEN` instead")]
20 pub const SERIALIZED_SIZE: usize = Ethernet2Header::LEN;
21
22 #[deprecated(since = "0.10.1", note = "Use Ethernet2Header::from_slice instead.")]
24 #[inline]
25 pub fn read_from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
26 Ethernet2Header::from_slice(slice)
27 }
28
29 #[inline]
31 pub fn from_slice(slice: &[u8]) -> Result<(Ethernet2Header, &[u8]), err::LenError> {
32 Ok((
33 Ethernet2HeaderSlice::from_slice(slice)?.to_header(),
34 &slice[Ethernet2Header::LEN..],
35 ))
36 }
37
38 #[inline]
40 pub fn from_bytes(bytes: [u8; 14]) -> Ethernet2Header {
41 Ethernet2Header {
42 destination: [bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]],
43 source: [bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11]],
44 ether_type: EtherType(u16::from_be_bytes([bytes[12], bytes[13]])),
45 }
46 }
47
48 #[cfg(feature = "std")]
50 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
51 pub fn read<T: std::io::Read + std::io::Seek + Sized>(
52 reader: &mut T,
53 ) -> Result<Ethernet2Header, std::io::Error> {
54 let buffer = {
55 let mut buffer = [0; Ethernet2Header::LEN];
56 reader.read_exact(&mut buffer)?;
57 buffer
58 };
59
60 Ok(
61 unsafe { Ethernet2HeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
63 )
64 }
65
66 pub fn write_to_slice<'a>(
68 &self,
69 slice: &'a mut [u8],
70 ) -> Result<&'a mut [u8], SliceWriteSpaceError> {
71 if slice.len() < Ethernet2Header::LEN {
73 Err(SliceWriteSpaceError {
74 required_len: Ethernet2Header::LEN,
75 len: slice.len(),
76 layer: Layer::Ethernet2Header,
77 layer_start_offset: 0,
78 })
79 } else {
80 slice[..Ethernet2Header::LEN].copy_from_slice(&self.to_bytes());
81 Ok(&mut slice[Ethernet2Header::LEN..])
82 }
83 }
84
85 #[cfg(feature = "std")]
87 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
88 #[inline]
89 pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
90 writer.write_all(&self.to_bytes())
91 }
92
93 #[inline]
95 pub fn header_len(&self) -> usize {
96 14
97 }
98
99 #[inline]
102 pub fn to_bytes(&self) -> [u8; 14] {
103 let ether_type_be = self.ether_type.0.to_be_bytes();
104 [
105 self.destination[0],
106 self.destination[1],
107 self.destination[2],
108 self.destination[3],
109 self.destination[4],
110 self.destination[5],
111 self.source[0],
112 self.source[1],
113 self.source[2],
114 self.source[3],
115 self.source[4],
116 self.source[5],
117 ether_type_be[0],
118 ether_type_be[1],
119 ]
120 }
121}
122
123#[cfg(test)]
124mod test {
125 use super::*;
126 use crate::test_gens::*;
127 use alloc::{format, vec::Vec};
128 use proptest::prelude::*;
129 use std::io::{Cursor, ErrorKind};
130
131 #[test]
132 fn default() {
133 let e: Ethernet2Header = Default::default();
134 assert_eq!([0u8; 6], e.source);
135 assert_eq!([0u8; 6], e.destination);
136 assert_eq!(EtherType(0), e.ether_type);
137 }
138
139 proptest! {
140 #[test]
141 fn from_slice(
142 input in ethernet_2_any(),
143 dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
144 ) {
145 let mut buffer: Vec<u8> = Vec::with_capacity(14 + dummy_data.len());
147 input.write(&mut buffer).unwrap();
148 buffer.extend(&dummy_data[..]);
149
150 {
152 let (result, rest) = Ethernet2Header::from_slice(&buffer[..]).unwrap();
153 assert_eq!(input, result);
154 assert_eq!(&buffer[14..], rest);
155 }
156 #[allow(deprecated)]
157 {
158 let (result, rest) = Ethernet2Header::read_from_slice(&buffer[..]).unwrap();
159 assert_eq!(input, result);
160 assert_eq!(&buffer[14..], rest);
161 }
162
163 for len in 0..=13 {
165 assert_eq!(
166 Ethernet2Header::from_slice(&buffer[..len]),
167 Err(err::LenError{
168 required_len: Ethernet2Header::LEN,
169 len: len,
170 len_source: LenSource::Slice,
171 layer: err::Layer::Ethernet2Header,
172 layer_start_offset: 0,
173 })
174 );
175 }
176 }
177 }
178
179 proptest! {
180 #[test]
181 fn from_bytes(input in ethernet_2_any()) {
182 assert_eq!(
183 input,
184 Ethernet2Header::from_bytes(input.to_bytes())
185 );
186 }
187 }
188
189 proptest! {
190 #[test]
191 fn read(
192 input in ethernet_2_any(),
193 dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
194 ) {
195 let mut buffer = Vec::with_capacity(14 + dummy_data.len());
197 input.write(&mut buffer).unwrap();
198 buffer.extend(&dummy_data[..]);
199
200 {
202 let mut cursor = Cursor::new(&buffer);
203 let result = Ethernet2Header::read(&mut cursor).unwrap();
204 assert_eq!(input, result);
205 assert_eq!(cursor.position(), 14);
206 }
207
208 for len in 0..=13 {
210 let mut cursor = Cursor::new(&buffer[0..len]);
211 assert_eq!(
212 Ethernet2Header::read(&mut cursor)
213 .unwrap_err()
214 .kind(),
215 ErrorKind::UnexpectedEof
216 );
217 }
218 }
219 }
220
221 proptest! {
222 #[test]
223 fn write_to_slice(input in ethernet_2_any()) {
224 {
226 let mut buffer: [u8;14] = [0;14];
227 input.write_to_slice(&mut buffer).unwrap();
228 assert_eq!(buffer, input.to_bytes());
229 }
230 for len in 0..14 {
232 let mut buffer: [u8;14] = [0;14];
233 assert_eq!(
234 SliceWriteSpaceError {
235 required_len: Ethernet2Header::LEN,
236 len,
237 layer: Layer::Ethernet2Header,
238 layer_start_offset: 0,
239 },
240 input.write_to_slice(&mut buffer[..len]).unwrap_err()
241 );
242 }
243 }
244 }
245
246 proptest! {
247 #[test]
248 fn write(input in ethernet_2_any()) {
249 {
251 let mut buffer: Vec<u8> = Vec::with_capacity(14);
252 input.write(&mut buffer).unwrap();
253 assert_eq!(&buffer[..], &input.to_bytes());
254 }
255
256 for len in 0..8 {
258 let mut buffer = [0u8;8];
259 let mut writer = Cursor::new(&mut buffer[..len]);
260 assert!(input.write(&mut writer).is_err());
261 }
262 }
263 }
264
265 proptest! {
266 #[test]
267 fn header_len(input in ethernet_2_any()) {
268 assert_eq!(input.header_len(), 14);
269 }
270 }
271
272 proptest! {
273 #[test]
274 fn to_bytes(input in ethernet_2_any()) {
275 let ether_type_be = input.ether_type.0.to_be_bytes();
276 assert_eq!(
277 input.to_bytes(),
278 [
279 input.destination[0],
280 input.destination[1],
281 input.destination[2],
282 input.destination[3],
283 input.destination[4],
284 input.destination[5],
285 input.source[0],
286 input.source[1],
287 input.source[2],
288 input.source[3],
289 input.source[4],
290 input.source[5],
291 ether_type_be[0],
292 ether_type_be[1],
293 ]
294 );
295 }
296 }
297
298 proptest! {
299 #[test]
300 fn clone_eq(input in ethernet_2_any()) {
301 assert_eq!(input, input.clone());
302 }
303 }
304
305 proptest! {
306 #[test]
307 fn dbg(input in ethernet_2_any()) {
308 assert_eq!(
309 &format!(
310 "Ethernet2Header {{ source: {:?}, destination: {:?}, ether_type: {:?} }}",
311 input.source,
312 input.destination,
313 input.ether_type
314 ),
315 &format!("{:?}", input)
316 );
317 }
318 }
319}