1use crate::*;
2
3#[cfg(feature = "std")]
5#[deprecated(
6 since = "0.14.0",
7 note = "Deprecated use crate::NetSlice or crate::IpSlice instead"
8)]
9pub use NetSlice as InternetSlice;
10
11#[derive(Clone, Debug, Eq, PartialEq)]
13pub enum NetSlice<'a> {
14 Ipv4(Ipv4Slice<'a>),
16 Ipv6(Ipv6Slice<'a>),
18 Arp(ArpPacketSlice<'a>),
20}
21
22impl<'a> NetSlice<'a> {
23 #[inline]
25 pub fn is_ip(&self) -> bool {
26 use NetSlice::*;
27 matches!(self, Ipv4(_) | Ipv6(_))
28 }
29
30 #[inline]
32 pub fn is_ipv4(&self) -> bool {
33 use NetSlice::*;
34 matches!(self, Ipv4(_))
35 }
36
37 #[inline]
39 pub fn is_ipv6(&self) -> bool {
40 use NetSlice::*;
41 matches!(self, Ipv6(_))
42 }
43
44 #[inline]
46 pub fn is_arp(&self) -> bool {
47 use NetSlice::*;
48 matches!(self, Arp(_))
49 }
50
51 #[inline]
53 pub fn ipv4_ref(&self) -> Option<&Ipv4Slice<'a>> {
54 if let NetSlice::Ipv4(s) = self {
55 Some(s)
56 } else {
57 None
58 }
59 }
60
61 #[inline]
63 pub fn ipv6_ref(&self) -> Option<&Ipv6Slice<'a>> {
64 if let NetSlice::Ipv6(s) = self {
65 Some(s)
66 } else {
67 None
68 }
69 }
70
71 #[inline]
73 pub fn arp_ref(&self) -> Option<&ArpPacketSlice> {
74 if let NetSlice::Arp(arp) = self {
75 Some(arp)
76 } else {
77 None
78 }
79 }
80
81 #[inline]
84 pub fn ip_payload_ref(&self) -> Option<&IpPayloadSlice<'a>> {
85 match self {
86 NetSlice::Ipv4(s) => Some(&s.payload),
87 NetSlice::Ipv6(s) => Some(&s.payload),
88 NetSlice::Arp(_) => None,
89 }
90 }
91}
92
93impl<'a> From<IpSlice<'a>> for NetSlice<'a> {
94 #[inline]
95 fn from(value: IpSlice<'a>) -> NetSlice<'a> {
96 match value {
97 IpSlice::Ipv4(ipv4) => NetSlice::Ipv4(ipv4),
98 IpSlice::Ipv6(ipv6) => NetSlice::Ipv6(ipv6),
99 }
100 }
101}
102
103impl<'a> From<Ipv4Slice<'a>> for NetSlice<'a> {
104 #[inline]
105 fn from(value: Ipv4Slice<'a>) -> NetSlice<'a> {
106 NetSlice::Ipv4(value)
107 }
108}
109
110impl<'a> From<Ipv6Slice<'a>> for NetSlice<'a> {
111 #[inline]
112 fn from(value: Ipv6Slice<'a>) -> NetSlice<'a> {
113 NetSlice::Ipv6(value)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use crate::*;
120 use alloc::{format, vec::Vec};
121
122 #[test]
123 fn debug() {
124 let bytes = Ipv6Header {
125 next_header: IpNumber::UDP,
126 ..Default::default()
127 }
128 .to_bytes();
129 let s = Ipv6Slice::from_slice(&bytes).unwrap();
130 let n = NetSlice::Ipv6(s.clone());
131 assert_eq!(format!("{n:?}"), format!("Ipv6({s:?})"));
132 }
133
134 #[test]
135 fn clone_eq() {
136 let bytes = Ipv6Header {
137 next_header: IpNumber::UDP,
138 ..Default::default()
139 }
140 .to_bytes();
141 let s = NetSlice::Ipv6(Ipv6Slice::from_slice(&bytes).unwrap());
142 assert_eq!(s, s.clone())
143 }
144
145 #[test]
146 fn ip_payload_ref_and_is_ip() {
147 {
149 let payload = [1, 2, 3, 4];
150 let bytes = {
151 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
152 bytes.extend_from_slice(
153 &(Ipv4Header {
154 total_len: Ipv4Header::MIN_LEN_U16 + 4,
155 protocol: IpNumber::UDP,
156 ..Default::default()
157 })
158 .to_bytes(),
159 );
160 bytes.extend_from_slice(&payload);
161 bytes
162 };
163 let p = Ipv4Slice::from_slice(&bytes).unwrap();
164 let s = NetSlice::Ipv4(p.clone());
165 assert_eq!(
166 s.ip_payload_ref(),
167 Some(&IpPayloadSlice {
168 ip_number: IpNumber::UDP,
169 fragmented: false,
170 len_source: LenSource::Ipv4HeaderTotalLen,
171 payload: &payload
172 })
173 );
174 assert!(s.is_ip());
175 assert!(s.is_ipv4());
176 assert_eq!(false, s.is_ipv6());
177 assert_eq!(false, s.is_arp());
178 assert_eq!(Some(&p), s.ipv4_ref());
179 assert_eq!(None, s.ipv6_ref());
180 assert_eq!(None, s.arp_ref());
181 }
182 {
184 let payload = [1, 2, 3, 4];
185 let bytes = {
186 let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
187 bytes.extend_from_slice(
188 &(Ipv6Header {
189 next_header: IpNumber::UDP,
190 payload_length: 4,
191 ..Default::default()
192 })
193 .to_bytes(),
194 );
195 bytes.extend_from_slice(&payload);
196 bytes
197 };
198 let p = Ipv6Slice::from_slice(&bytes).unwrap();
199 let s = NetSlice::Ipv6(p.clone());
200 assert_eq!(
201 s.ip_payload_ref(),
202 Some(&IpPayloadSlice {
203 ip_number: IpNumber::UDP,
204 fragmented: false,
205 len_source: LenSource::Ipv6HeaderPayloadLen,
206 payload: &payload
207 })
208 );
209 assert!(s.is_ip());
210 assert_eq!(false, s.is_ipv4());
211 assert!(s.is_ipv6());
212 assert_eq!(false, s.is_arp());
213 assert_eq!(None, s.ipv4_ref());
214 assert_eq!(Some(&p), s.ipv6_ref());
215 assert_eq!(None, s.arp_ref());
216 }
217 {
219 let arp = ArpPacket::new(
220 ArpHardwareId::ETHERNET,
221 EtherType::IPV4,
222 ArpOperation::REPLY,
223 &[0; 6],
224 &[0; 4],
225 &[0; 6],
226 &[0; 4],
227 )
228 .unwrap();
229 let bytes = arp.to_bytes();
230 let p = ArpPacketSlice::from_slice(&bytes).unwrap();
231 let s = NetSlice::Arp(p.clone());
232 assert_eq!(None, s.ip_payload_ref());
233 assert_eq!(false, s.is_ip());
234 assert_eq!(false, s.is_ipv4());
235 assert_eq!(false, s.is_ipv6());
236 assert!(s.is_arp());
237 assert_eq!(None, s.ipv4_ref());
238 assert_eq!(None, s.ipv6_ref());
239 assert_eq!(Some(&p), s.arp_ref());
240 }
241 }
242
243 #[test]
244 fn from() {
245 {
247 let payload = [1, 2, 3, 4];
248 let bytes = {
249 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
250 bytes.extend_from_slice(
251 &(Ipv4Header {
252 total_len: Ipv4Header::MIN_LEN_U16 + 4,
253 protocol: IpNumber::UDP,
254 ..Default::default()
255 })
256 .to_bytes(),
257 );
258 bytes.extend_from_slice(&payload);
259 bytes
260 };
261 let i = Ipv4Slice::from_slice(&bytes).unwrap();
262 let actual: NetSlice = IpSlice::Ipv4(i.clone()).into();
263 assert_eq!(NetSlice::Ipv4(i.clone()), actual);
264 }
265 {
267 let payload = [1, 2, 3, 4];
268 let bytes = {
269 let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
270 bytes.extend_from_slice(
271 &(Ipv4Header {
272 total_len: Ipv4Header::MIN_LEN_U16 + 4,
273 protocol: IpNumber::UDP,
274 ..Default::default()
275 })
276 .to_bytes(),
277 );
278 bytes.extend_from_slice(&payload);
279 bytes
280 };
281 let i = Ipv4Slice::from_slice(&bytes).unwrap();
282 let actual: NetSlice = i.clone().into();
283 assert_eq!(NetSlice::Ipv4(i.clone()), actual);
284 }
285 {
287 let payload = [1, 2, 3, 4];
288 let bytes = {
289 let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
290 bytes.extend_from_slice(
291 &(Ipv6Header {
292 next_header: IpNumber::UDP,
293 payload_length: 4,
294 ..Default::default()
295 })
296 .to_bytes(),
297 );
298 bytes.extend_from_slice(&payload);
299 bytes
300 };
301 let i = Ipv6Slice::from_slice(&bytes).unwrap();
302 let actual: NetSlice = i.clone().into();
303 assert_eq!(NetSlice::Ipv6(i.clone()), actual);
304 }
305 }
306}