etherparse/link/
link_slice.rs1use crate::*;
2
3#[derive(Clone, Debug, Eq, PartialEq)]
6pub enum LinkSlice<'a> {
7 Ethernet2(Ethernet2Slice<'a>),
9
10 LinuxSll(LinuxSllSlice<'a>),
12
13 EtherPayload(EtherPayloadSlice<'a>),
15
16 LinuxSllPayload(LinuxSllPayloadSlice<'a>),
18}
19
20impl<'a> LinkSlice<'a> {
21 pub fn to_header(&self) -> Option<LinkHeader> {
23 use LinkSlice::*;
24 match self {
25 Ethernet2(slice) => Some(LinkHeader::Ethernet2(slice.to_header())),
26 LinuxSll(slice) => Some(LinkHeader::LinuxSll(slice.to_header())),
27 EtherPayload(_) => None,
28 LinuxSllPayload(_) => None,
29 }
30 }
31
32 pub fn ether_payload(&self) -> Option<EtherPayloadSlice<'a>> {
34 use LinkSlice::*;
35 match self {
36 Ethernet2(s) => Some(s.payload().clone()),
37 LinuxSll(s) => Some(EtherPayloadSlice::try_from(s.payload()).ok()?.clone()),
38 EtherPayload(p) => Some(p.clone()),
39 LinuxSllPayload(p) => Some(EtherPayloadSlice::try_from(p.clone()).ok()?),
40 }
41 }
42
43 pub fn sll_payload(&self) -> LinuxSllPayloadSlice<'a> {
45 use LinkSlice::*;
46 match self {
47 Ethernet2(s) => LinuxSllPayloadSlice::from(s.payload().clone()),
48 LinuxSll(s) => s.payload().clone(),
49 EtherPayload(p) => LinuxSllPayloadSlice::from(p.clone()),
50 LinuxSllPayload(p) => p.clone(),
51 }
52 }
53}
54
55#[cfg(test)]
56mod test {
57 use super::*;
58 use crate::test_gens::*;
59 use alloc::{format, vec::Vec};
60 use proptest::prelude::*;
61
62 proptest! {
63 #[test]
64 fn debug_clone_eq(ref eth in ethernet_2_unknown()) {
65 let bytes = eth.to_bytes();
66 let e = Ethernet2Slice::from_slice_without_fcs(&bytes).unwrap();
67 let slice = LinkSlice::Ethernet2(
68 e.clone()
69 );
70
71 assert_eq!(slice.clone(), slice);
73
74 assert_eq!(
76 format!("{:?}", slice),
77 format!("Ethernet2({:?})", e),
78 );
79 }
80 }
81
82 proptest! {
83 #[test]
84 fn to_header(
85 ref eth in ethernet_2_unknown(),
86 ref linux_sll in linux_sll_any()
87 ) {
88 {
89 let bytes = eth.to_bytes();
90 let slice = LinkSlice::Ethernet2(
91 Ethernet2Slice::from_slice_without_fcs(&bytes).unwrap()
92 );
93 assert_eq!(
94 slice.to_header(),
95 Some(LinkHeader::Ethernet2(eth.clone()))
96 );
97 }
98 {
99 let bytes = linux_sll.to_bytes();
100 let slice = LinkSlice::LinuxSll(
101 LinuxSllSlice::from_slice(&bytes).unwrap()
102 );
103 assert_eq!(
104 slice.to_header(),
105 Some(LinkHeader::LinuxSll(linux_sll.clone()))
106 );
107 }
108 {
109 let slice = LinkSlice::EtherPayload(EtherPayloadSlice {
110 ether_type: ether_type::IPV4,
111 len_source: LenSource::Slice,
112 payload: &[]
113 });
114 assert_eq!(
115 slice.to_header(),
116 None
117 );
118 }
119 {
120 let slice = LinkSlice::LinuxSllPayload(LinuxSllPayloadSlice {
121 protocol_type: LinuxSllProtocolType::EtherType(ether_type::IPV4),
122 payload: &[]
123 });
124 assert_eq!(
125 slice.to_header(),
126 None
127 );
128 }
129 }
130 }
131
132 proptest! {
133 #[test]
134 fn ether_payload(
135 ref eth in ethernet_2_unknown(),
136 ref linux_sll in linux_sll_any()
137 ) {
138 let p = [1,2,3,4];
139 {
140 let mut bytes = Vec::with_capacity(Ethernet2Header::LEN + p.len());
141 bytes.extend_from_slice(ð.to_bytes());
142 bytes.extend_from_slice(&p);
143 let slice = LinkSlice::Ethernet2(
144 Ethernet2Slice::from_slice_without_fcs(&bytes).unwrap()
145 );
146 assert_eq!(
147 slice.ether_payload().unwrap(),
148 EtherPayloadSlice{
149 ether_type: eth.ether_type,
150 len_source: LenSource::Slice,
151 payload: &p
152 }
153 );
154 }
155 {
156 let slice = LinkSlice::EtherPayload(EtherPayloadSlice {
157 ether_type: eth.ether_type,
158 len_source: LenSource::Slice,
159 payload: &p
160 });
161 assert_eq!(
162 slice.ether_payload().unwrap(),
163 EtherPayloadSlice{
164 ether_type: eth.ether_type,
165 len_source: LenSource::Slice,
166 payload: &p
167 }
168 );
169 }
170 {
171 let mut bytes = Vec::with_capacity(LinuxSllHeader::LEN + p.len());
172 bytes.extend_from_slice(&linux_sll.to_bytes());
173 bytes.extend_from_slice(&p);
174 let slice = LinkSlice::LinuxSll(
175 LinuxSllSlice::from_slice(&bytes).unwrap()
176 );
177 match linux_sll.protocol_type {
178 LinuxSllProtocolType::EtherType(EtherType(v)) | LinuxSllProtocolType::LinuxNonstandardEtherType(LinuxNonstandardEtherType(v)) => { assert_eq!(
179 slice.ether_payload().unwrap(),
180 EtherPayloadSlice{
181 ether_type: EtherType(v),
182 len_source: LenSource::Slice,
183 payload: &p,
184 }
185 );}
186 _ => { assert!(slice.ether_payload().is_none());}
187 }
188 }
189 {
190 let slice = LinkSlice::LinuxSllPayload(LinuxSllPayloadSlice {
191 protocol_type: linux_sll.protocol_type,
192 payload: &p
193 });
194 match linux_sll.protocol_type {
195 LinuxSllProtocolType::EtherType(EtherType(v)) | LinuxSllProtocolType::LinuxNonstandardEtherType(LinuxNonstandardEtherType(v)) => { assert_eq!(
196 slice.ether_payload().unwrap(),
197 EtherPayloadSlice{
198 ether_type: EtherType(v),
199 len_source: LenSource::Slice,
200 payload: &p,
201 }
202 );}
203 _ => { assert!(slice.ether_payload().is_none());}
204 }
205 }
206 }
207 }
208
209 proptest! {
210 #[test]
211 fn sll_payload(
212 ref eth in ethernet_2_unknown(),
213 ref linux_sll in linux_sll_any()
214 ) {
215 let p = [1,2,3,4];
216 {
217 let mut bytes = Vec::with_capacity(Ethernet2Header::LEN + p.len());
218 bytes.extend_from_slice(ð.to_bytes());
219 bytes.extend_from_slice(&p);
220 let slice = LinkSlice::Ethernet2(
221 Ethernet2Slice::from_slice_without_fcs(&bytes).unwrap()
222 );
223 assert_eq!(
224 slice.sll_payload(),
225 LinuxSllPayloadSlice{
226 protocol_type: LinuxSllProtocolType::EtherType(eth.ether_type),
227 payload: &p
228 }
229 );
230 }
231 {
232 let slice = LinkSlice::EtherPayload(EtherPayloadSlice {
233 ether_type: eth.ether_type,
234 len_source: LenSource::Slice,
235 payload: &p
236 });
237 assert_eq!(
238 slice.sll_payload(),
239 LinuxSllPayloadSlice{
240 protocol_type: LinuxSllProtocolType::EtherType(eth.ether_type),
241 payload: &p
242 }
243 );
244 }
245 {
246 let mut bytes = Vec::with_capacity(LinuxSllHeader::LEN + p.len());
247 bytes.extend_from_slice(&linux_sll.to_bytes());
248 bytes.extend_from_slice(&p);
249 let slice = LinkSlice::LinuxSll(
250 LinuxSllSlice::from_slice(&bytes).unwrap()
251 );
252 assert_eq!(
253 slice.sll_payload(),
254 LinuxSllPayloadSlice{
255 protocol_type: linux_sll.protocol_type,
256 payload: &p
257 }
258 );
259 }
260 {
261 let slice = LinkSlice::LinuxSllPayload(LinuxSllPayloadSlice {
262 protocol_type: linux_sll.protocol_type,
263 payload: &p
264 });
265 assert_eq!(
266 slice.sll_payload(),
267 LinuxSllPayloadSlice{
268 protocol_type: linux_sll.protocol_type,
269 payload: &p
270 }
271 );
272 }
273 }
274 }
275}