s2n_quic_platform/bpf/
instruction.rs1use core::{fmt, marker::PhantomData, ops};
5use libc::sock_filter;
6
7pub trait Dialect: Sized {
8 const MAX_INSTRUCTIONS: usize;
9 const SOCKOPT: libc::c_int;
10
11 fn debug(instruction: &Instruction<Self>, f: &mut fmt::Formatter) -> fmt::Result;
12 fn display(
13 instruction: &Instruction<Self>,
14 f: &mut fmt::Formatter,
15 idx: Option<usize>,
16 ) -> fmt::Result;
17}
18
19#[derive(Clone, Copy)]
20#[repr(transparent)]
21pub struct Instruction<D: Dialect>(sock_filter, PhantomData<D>);
22
23impl<D: Dialect> ops::Deref for Instruction<D> {
24 type Target = sock_filter;
25
26 #[inline]
27 fn deref(&self) -> &Self::Target {
28 &self.0
29 }
30}
31
32impl<D: Dialect> fmt::Debug for Instruction<D> {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 D::debug(self, f)
35 }
36}
37
38impl<D: Dialect> fmt::Display for Instruction<D> {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 if f.alternate() {
41 let k_prefix = if self.k == 0 { "00" } else { "0x" };
43 write!(
44 f,
45 "{{ 0x{:0>2x}, {:>2}, {:>2}, {k_prefix}{:0>8x} }}",
46 self.code, self.jt, self.jf, self.k
47 )
48 } else {
49 D::display(self, f, None)
50 }
51 }
52}
53
54macro_rules! define {
55 (#[mask($mask:literal)]
56 pub enum $ty:ident {
57 $(
58 $OP:ident = $value:literal
59 ),*
60 $(,)?
61 }) => {
62 #[repr(u16)]
63 #[derive(Copy, Clone, Debug)]
64 #[allow(clippy::upper_case_acronyms, non_camel_case_types)]
65 pub enum $ty {
66 $(
67 $OP = $value,
68 )*
69 }
70
71 impl core::fmt::Display for $ty {
72 #[inline]
73 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
74 self.to_str().fmt(f)
75 }
76 }
77
78 impl $ty {
79 #[inline]
80 pub fn decode(op: u16) -> Self {
81 match op & $mask {
82 $(
83 op if op == $value => Self::$OP,
84 )*
85 _ => unreachable!(),
86 }
87 }
88
89 #[inline]
90 pub const fn to_str(self) -> &'static str {
91 match self {
92 $(
93 Self::$OP => stringify!($OP),
94 )*
95 }
96 }
97 }
98 }
99}
100
101impl<D: Dialect> Instruction<D> {
102 pub const fn raw(code: u16, jt: u8, jf: u8, k: u32) -> Self {
103 Instruction(libc::sock_filter { code, jt, jf, k }, PhantomData)
104 }
105}