zero_packet/network/extensions/
fragment.rs1use core::fmt;
2
3pub const FRAGMENT_HEADER_LENGTH: usize = 8;
5
6pub struct FragmentHeaderWriter<'a> {
8 pub bytes: &'a mut [u8],
9}
10
11impl<'a> FragmentHeaderWriter<'a> {
12 #[inline]
14 pub fn new(bytes: &'a mut [u8]) -> Result<Self, &'static str> {
15 if bytes.len() < FRAGMENT_HEADER_LENGTH {
16 panic!("Slice is too short to contain a Fragment header.");
17 }
18
19 Ok(Self { bytes })
20 }
21
22 #[inline]
24 pub fn header_len(&self) -> usize {
25 FRAGMENT_HEADER_LENGTH
26 }
27
28 #[inline]
32 pub fn set_next_header(&mut self, next_header: u8) {
33 self.bytes[0] = next_header;
34 }
35
36 #[inline]
40 pub fn set_reserved(&mut self, reserved: u8) {
41 self.bytes[1] = reserved;
42 }
43
44 #[inline]
48 pub fn set_fragment_offset(&mut self, fragment_offset: u16) {
49 let value = fragment_offset & 0x1FFF;
51 self.bytes[2] = (value >> 5) as u8;
52 self.bytes[3] = (self.bytes[3] & 0xE0) | ((value & 0x1F) as u8);
53 }
54
55 #[inline]
59 pub fn set_res(&mut self, res: u8) {
60 let value = res & 0b11;
62 self.bytes[3] = (self.bytes[3] & 0x9F) | (value << 5);
63 }
64
65 #[inline]
69 pub fn set_m_flag(&mut self, m_flag: bool) {
70 if m_flag {
72 self.bytes[3] |= 0x80;
73 } else {
74 self.bytes[3] &= 0x7F;
75 }
76 }
77
78 #[inline]
82 pub fn set_identification(&mut self, identification: u32) {
83 self.bytes[4] = (identification >> 24) as u8;
84 self.bytes[5] = (identification >> 16) as u8;
85 self.bytes[6] = (identification >> 8) as u8;
86 self.bytes[7] = identification as u8;
87 }
88}
89
90pub struct FragmentHeaderReader<'a> {
92 pub bytes: &'a [u8],
93}
94
95impl<'a> FragmentHeaderReader<'a> {
96 #[inline]
97 pub fn new(bytes: &'a [u8]) -> Result<Self, &'static str> {
98 if bytes.len() < FRAGMENT_HEADER_LENGTH {
99 return Err("Slice is too short to contain a Fragment header.");
100 }
101
102 Ok(Self { bytes })
103 }
104
105 #[inline]
109 pub fn next_header(&self) -> u8 {
110 self.bytes[0]
111 }
112
113 #[inline]
117 pub fn reserved(&self) -> u8 {
118 self.bytes[1]
119 }
120
121 #[inline]
125 pub fn fragment_offset(&self) -> u16 {
126 ((self.bytes[2] as u16) << 5) | ((self.bytes[3] & 0x1F) as u16)
127 }
128
129 #[inline]
133 pub fn res(&self) -> u8 {
134 (self.bytes[3] >> 5) & 0b11
135 }
136
137 #[inline]
141 pub fn m_flag(&self) -> bool {
142 (self.bytes[3] & 0x80) != 0
143 }
144
145 #[inline]
149 pub fn identification(&self) -> u32 {
150 ((self.bytes[4] as u32) << 24)
151 | ((self.bytes[5] as u32) << 16)
152 | ((self.bytes[6] as u32) << 8)
153 | (self.bytes[7] as u32)
154 }
155
156 #[inline]
158 pub fn header_len(&self) -> usize {
159 FRAGMENT_HEADER_LENGTH
160 }
161
162 #[inline]
164 pub fn header(&self) -> &'a [u8] {
165 &self.bytes[..FRAGMENT_HEADER_LENGTH]
166 }
167
168 #[inline]
170 pub fn payload(&self) -> &'a [u8] {
171 &self.bytes[FRAGMENT_HEADER_LENGTH..]
172 }
173}
174
175impl fmt::Debug for FragmentHeaderReader<'_> {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.debug_struct("FragmentHeader")
178 .field("next_header", &self.next_header())
179 .field("reserved", &self.reserved())
180 .field("fragment_offset", &self.fragment_offset())
181 .field("res", &self.res())
182 .field("m_flag", &self.m_flag())
183 .field("identification", &self.identification())
184 .finish()
185 }
186}
187
188#[cfg(test)]
189pub mod tests {
190 use super::*;
191
192 #[test]
193 fn getters_and_setters() {
194 let mut bytes = [0u8; 16];
196
197 let next_header = 6;
199 let reserved = 0;
200 let fragment_offset = 255;
201 let res = 0;
202 let m_flag = true;
203 let identification = 0x04050607;
204
205 let mut writer = FragmentHeaderWriter::new(&mut bytes).unwrap();
207
208 writer.set_next_header(next_header);
210 writer.set_reserved(reserved);
211 writer.set_fragment_offset(fragment_offset);
212 writer.set_res(res);
213 writer.set_m_flag(m_flag);
214 writer.set_identification(identification);
215
216 let reader = FragmentHeaderReader::new(&bytes).unwrap();
218
219 assert_eq!(reader.next_header(), next_header);
221 assert_eq!(reader.reserved(), reserved);
222 assert_eq!(reader.fragment_offset(), fragment_offset);
223 assert_eq!(reader.res(), res);
224 assert_eq!(reader.m_flag(), m_flag);
225 assert_eq!(reader.identification(), identification);
226 }
227}