wlan_hw_sim/event/
buffered.rs1use fidl_fuchsia_wlan_tap as fidl_tap;
17use std::borrow::Borrow;
18use std::fmt::Debug;
19use std::marker::PhantomData;
20use wlan_common::mac::{
21 self, ActionBody, AssocReqFrame as ParsedAssocReqFrame, AssocRespFrame as ParsedAssocRespFrame,
22 AuthFrame as ParsedAuthFrame, DataFrame as ParsedDataFrame, MacFrame as ParsedMacFrame,
23 MgmtFrame as ParsedMgmtFrame, NoAck, ProbeReqFrame as ParsedProbeReqFrame,
24};
25use zerocopy::SplitByteSlice;
26
27use crate::event::extract::FromEvent;
28
29pub type ParsedActionFrame<const NO_ACK: bool, B> = NoAck<NO_ACK, ActionBody<B>>;
30
31mod sealed {
32 use super::*;
33
34 pub trait AsBuffer<T>
35 where
36 T: Parse,
37 {
38 fn as_buffer(&self) -> Option<&[u8]>;
39 }
40}
41use sealed::AsBuffer;
42
43pub trait Parse {
44 type Output<B>
45 where
46 B: SplitByteSlice;
47
48 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
49 where
50 B: SplitByteSlice;
51}
52
53pub trait TaggedField: Parse {
54 type Tag: Tag;
55
56 fn tag<B>(parsed: &Self::Output<B>) -> Self::Tag
57 where
58 B: SplitByteSlice;
59}
60
61pub trait TaggedVariant<T>
62where
63 T: TaggedField,
64{
65 const TAG: T::Tag;
66
67 fn has_tag(tag: impl Borrow<T::Tag>) -> bool {
68 Self::TAG.eq(tag.borrow())
69 }
70}
71
72pub trait Tag: Eq {
73 fn is_supported(&self) -> bool;
74}
75
76impl Tag for mac::FrameType {
77 fn is_supported(&self) -> bool {
78 mac::FrameType::is_supported(self)
79 }
80}
81
82impl Tag for mac::MgmtSubtype {
83 fn is_supported(&self) -> bool {
84 mac::MgmtSubtype::is_supported(self)
85 }
86}
87
88pub enum MacFrame {}
89
90impl AsBuffer<MacFrame> for fidl_tap::TxArgs {
91 fn as_buffer(&self) -> Option<&[u8]> {
92 Some(&self.packet.data)
93 }
94}
95
96impl Parse for MacFrame {
97 type Output<B>
98 = ParsedMacFrame<B>
99 where
100 B: SplitByteSlice;
101
102 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
103 where
104 B: SplitByteSlice,
105 {
106 ParsedMacFrame::parse(bytes, false)
107 }
108}
109
110impl TaggedField for MacFrame {
111 type Tag = mac::FrameType;
112
113 fn tag<B>(frame: &Self::Output<B>) -> Self::Tag
114 where
115 B: SplitByteSlice,
116 {
117 match frame {
118 ParsedMacFrame::Ctrl { .. } => mac::FrameType::CTRL,
119 ParsedMacFrame::Data { .. } => mac::FrameType::DATA,
120 ParsedMacFrame::Mgmt { .. } => mac::FrameType::MGMT,
121 ParsedMacFrame::Unsupported { frame_ctrl } => { *frame_ctrl }.frame_type(),
122 }
123 }
124}
125
126pub enum DataFrame {}
127
128impl AsBuffer<DataFrame> for fidl_tap::TxArgs {
129 fn as_buffer(&self) -> Option<&[u8]> {
130 Some(&self.packet.data)
131 }
132}
133
134impl Parse for DataFrame {
135 type Output<B>
136 = ParsedDataFrame<B>
137 where
138 B: SplitByteSlice;
139
140 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
141 where
142 B: SplitByteSlice,
143 {
144 ParsedDataFrame::parse(bytes, false)
145 }
146}
147
148impl TaggedVariant<MacFrame> for DataFrame {
149 const TAG: <MacFrame as TaggedField>::Tag = mac::FrameType::DATA;
150}
151
152pub enum MgmtFrame {}
153
154impl AsBuffer<MgmtFrame> for fidl_tap::TxArgs {
155 fn as_buffer(&self) -> Option<&[u8]> {
156 Some(&self.packet.data)
157 }
158}
159
160impl Parse for MgmtFrame {
161 type Output<B>
162 = ParsedMgmtFrame<B>
163 where
164 B: SplitByteSlice;
165
166 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
167 where
168 B: SplitByteSlice,
169 {
170 ParsedMgmtFrame::parse(bytes, false)
171 }
172}
173
174impl TaggedField for MgmtFrame {
175 type Tag = mac::MgmtSubtype;
176
177 fn tag<B>(frame: &Self::Output<B>) -> Self::Tag
178 where
179 B: SplitByteSlice,
180 {
181 { frame.mgmt_hdr.frame_ctrl }.mgmt_subtype()
182 }
183}
184
185impl TaggedVariant<MacFrame> for MgmtFrame {
186 const TAG: <MacFrame as TaggedField>::Tag = mac::FrameType::MGMT;
187}
188
189pub enum ActionFrame<const NO_ACK: bool> {}
190
191impl AsBuffer<ActionFrame<false>> for fidl_tap::TxArgs {
192 fn as_buffer(&self) -> Option<&[u8]> {
193 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false).and_then(|frame| {
194 ActionFrame::<false>::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body)
195 })
196 }
197}
198
199impl AsBuffer<ActionFrame<true>> for fidl_tap::TxArgs {
200 fn as_buffer(&self) -> Option<&[u8]> {
201 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false).and_then(|frame| {
202 ActionFrame::<true>::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body)
203 })
204 }
205}
206
207impl<const NO_ACK: bool> Parse for ActionFrame<NO_ACK> {
208 type Output<B>
209 = ParsedActionFrame<NO_ACK, B>
210 where
211 B: SplitByteSlice;
212
213 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
214 where
215 B: SplitByteSlice,
216 {
217 NoAck::<NO_ACK, ActionBody<B>>::parse(bytes)
218 }
219}
220
221impl TaggedVariant<MgmtFrame> for ActionFrame<false> {
222 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::ACTION;
223}
224
225impl TaggedVariant<MgmtFrame> for ActionFrame<true> {
226 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::ACTION_NO_ACK;
227}
228
229pub enum AssocReqFrame {}
230
231impl AsBuffer<AssocReqFrame> for fidl_tap::TxArgs {
232 fn as_buffer(&self) -> Option<&[u8]> {
233 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false)
234 .and_then(|frame| AssocReqFrame::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body))
235 }
236}
237
238impl Parse for AssocReqFrame {
239 type Output<B>
240 = ParsedAssocReqFrame<B>
241 where
242 B: SplitByteSlice;
243
244 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
245 where
246 B: SplitByteSlice,
247 {
248 ParsedAssocReqFrame::parse(bytes)
249 }
250}
251
252impl TaggedVariant<MgmtFrame> for AssocReqFrame {
253 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::ASSOC_REQ;
254}
255
256pub enum AssocRespFrame {}
257
258impl AsBuffer<AssocRespFrame> for fidl_tap::TxArgs {
259 fn as_buffer(&self) -> Option<&[u8]> {
260 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false)
261 .and_then(|frame| AssocRespFrame::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body))
262 }
263}
264
265impl Parse for AssocRespFrame {
266 type Output<B>
267 = ParsedAssocRespFrame<B>
268 where
269 B: SplitByteSlice;
270
271 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
272 where
273 B: SplitByteSlice,
274 {
275 ParsedAssocRespFrame::parse(bytes)
276 }
277}
278
279impl TaggedVariant<MgmtFrame> for AssocRespFrame {
280 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::ASSOC_RESP;
281}
282
283pub enum AuthFrame {}
284
285impl AsBuffer<AuthFrame> for fidl_tap::TxArgs {
286 fn as_buffer(&self) -> Option<&[u8]> {
287 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false)
288 .and_then(|frame| AuthFrame::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body))
289 }
290}
291
292impl Parse for AuthFrame {
293 type Output<B>
294 = ParsedAuthFrame<B>
295 where
296 B: SplitByteSlice;
297
298 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
299 where
300 B: SplitByteSlice,
301 {
302 ParsedAuthFrame::parse(bytes)
303 }
304}
305
306impl TaggedVariant<MgmtFrame> for AuthFrame {
307 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::AUTH;
308}
309
310pub enum ProbeReqFrame {}
311
312impl AsBuffer<ProbeReqFrame> for fidl_tap::TxArgs {
313 fn as_buffer(&self) -> Option<&[u8]> {
314 ParsedMgmtFrame::parse(self.packet.data.as_slice(), false)
315 .and_then(|frame| ProbeReqFrame::has_tag(MgmtFrame::tag(&frame)).then_some(frame.body))
316 }
317}
318
319impl Parse for ProbeReqFrame {
320 type Output<B>
321 = ParsedProbeReqFrame<B>
322 where
323 B: SplitByteSlice;
324
325 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
326 where
327 B: SplitByteSlice,
328 {
329 ParsedProbeReqFrame::parse(bytes)
330 }
331}
332
333impl TaggedVariant<MgmtFrame> for ProbeReqFrame {
334 const TAG: <MgmtFrame as TaggedField>::Tag = mac::MgmtSubtype::PROBE_REQ;
335}
336
337pub struct Supported<T>(PhantomData<fn() -> T>);
342
343impl<T> Parse for Supported<T>
344where
345 T: Parse + TaggedField,
346{
347 type Output<B>
348 = T::Output<B>
349 where
350 B: SplitByteSlice;
351
352 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
353 where
354 B: SplitByteSlice,
355 {
356 T::parse(bytes).and_then(|parsed| T::tag(&parsed).is_supported().then_some(parsed))
357 }
358}
359
360impl<T, E> AsBuffer<Supported<T>> for E
361where
362 T: Parse + TaggedField,
363 E: AsBuffer<T>,
364{
365 fn as_buffer(&self) -> Option<&[u8]> {
366 AsBuffer::<T>::as_buffer(self)
367 }
368}
369
370pub struct Unsupported<T>(PhantomData<fn() -> T>);
375
376impl<T> Parse for Unsupported<T>
377where
378 T: Parse + TaggedField,
379{
380 type Output<B>
381 = T::Output<B>
382 where
383 B: SplitByteSlice;
384
385 fn parse<B>(bytes: B) -> Option<Self::Output<B>>
386 where
387 B: SplitByteSlice,
388 {
389 T::parse(bytes).and_then(|parsed| (!T::tag(&parsed).is_supported()).then_some(parsed))
390 }
391}
392
393impl<T, E> AsBuffer<Unsupported<T>> for E
394where
395 T: Parse + TaggedField,
396 E: AsBuffer<T>,
397{
398 fn as_buffer(&self) -> Option<&[u8]> {
399 AsBuffer::<T>::as_buffer(self)
400 }
401}
402
403#[derive(Clone, Debug)]
405pub struct Buffered<T>
406where
407 T: Parse,
408{
409 buffer: Vec<u8>,
410 phantom: PhantomData<fn() -> T>,
411}
412
413impl<T> Buffered<T>
414where
415 T: Parse,
416{
417 pub fn get(&self) -> T::Output<&'_ [u8]> {
419 T::parse(self.buffer.as_slice()).expect("buffered data failed to reparse")
420 }
421}
422
423impl<E, T> FromEvent<E> for Buffered<T>
424where
425 E: AsBuffer<T>,
426 T: Parse,
427{
428 fn from_event(event: &E) -> Option<Self> {
429 event.as_buffer().and_then(|buffer| {
434 T::parse(buffer).map(|_| Buffered { buffer: buffer.into(), phantom: PhantomData })
435 })
436 }
437}