net_wire/ethernet/
builder.rs1use core::fmt;
2
3use super::address::MacAddress;
4use super::ether_type::EtherType;
5use super::frame::{EthernetFrameMut, HEADER_LENGTH};
6
7const DESTINATION: core::ops::Range<usize> = 0..6;
8const SOURCE: core::ops::Range<usize> = 6..12;
9const ETHER_TYPE: core::ops::Range<usize> = 12..14;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub enum EthernetFrameBuildError {
17 MissingDestination,
19 MissingSource,
21 MissingEtherType,
23 LengthOverflow {
25 header_length: usize,
27 payload_length: usize,
29 },
30 BufferTooShort {
32 required: usize,
34 available: usize,
36 },
37}
38
39impl fmt::Display for EthernetFrameBuildError {
40 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 Self::MissingDestination => formatter.write_str("missing Ethernet destination address"),
43 Self::MissingSource => formatter.write_str("missing Ethernet source address"),
44 Self::MissingEtherType => formatter.write_str("missing Ethernet protocol type"),
45 Self::LengthOverflow {
46 header_length,
47 payload_length,
48 } => write!(
49 formatter,
50 "Ethernet frame length overflow: {header_length} + {payload_length}"
51 ),
52 Self::BufferTooShort {
53 required,
54 available,
55 } => write!(
56 formatter,
57 "Ethernet buffer is too short: need {required} bytes, have {available}"
58 ),
59 }
60 }
61}
62
63pub struct EthernetFrameBuilder<'a> {
69 buffer: &'a mut [u8],
70 payload_length: usize,
71 destination: Option<MacAddress>,
72 source: Option<MacAddress>,
73 ether_type: Option<EtherType>,
74}
75
76impl<'a> EthernetFrameBuilder<'a> {
77 #[inline]
82 pub fn new(buffer: &'a mut [u8], payload_length: usize) -> Self {
83 Self {
84 buffer,
85 payload_length,
86 destination: None,
87 source: None,
88 ether_type: None,
89 }
90 }
91
92 #[inline]
95 pub fn destination(mut self, destination: MacAddress) -> Self {
96 self.destination = Some(destination);
97 self
98 }
99
100 #[inline]
103 pub fn source(mut self, source: MacAddress) -> Self {
104 self.source = Some(source);
105 self
106 }
107
108 #[inline]
111 pub fn ether_type(mut self, ether_type: EtherType) -> Self {
112 self.ether_type = Some(ether_type);
113 self
114 }
115
116 #[inline]
122 pub fn build(self) -> Result<EthernetFrameMut<'a>, EthernetFrameBuildError> {
123 let destination = self
124 .destination
125 .ok_or(EthernetFrameBuildError::MissingDestination)?;
126 let source = self.source.ok_or(EthernetFrameBuildError::MissingSource)?;
127 let ether_type = self
128 .ether_type
129 .ok_or(EthernetFrameBuildError::MissingEtherType)?;
130 let frame_length = HEADER_LENGTH.checked_add(self.payload_length).ok_or(
131 EthernetFrameBuildError::LengthOverflow {
132 header_length: HEADER_LENGTH,
133 payload_length: self.payload_length,
134 },
135 )?;
136 if self.buffer.len() < frame_length {
137 return Err(EthernetFrameBuildError::BufferTooShort {
138 required: frame_length,
139 available: self.buffer.len(),
140 });
141 }
142
143 let bytes = &mut self.buffer[..frame_length];
144 bytes[DESTINATION].copy_from_slice(&destination.octets());
145 bytes[SOURCE].copy_from_slice(&source.octets());
146 bytes[ETHER_TYPE].copy_from_slice(ðer_type.raw().to_be_bytes());
147 Ok(EthernetFrameMut::from_validated(bytes))
148 }
149}