dope_sys/io/socket/route/
selector.rs1use std::num;
2
3use o3::buffer::bytes::scope;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub struct Selector {
8 branch_at: u8,
9 branch_mask: num::NonZero<u8>,
10 clear_key: u8,
11 clear_min: num::NonZero<u8>,
12 length_at: u8,
13 length: u8,
14 set_key: u8,
15 set_min: num::NonZero<u8>,
16}
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub struct PrefixPlan {
21 extent: num::NonZero<u8>,
22 raw_mask: num::NonZero<u8>,
23 tags: [u8; 2],
24}
25
26#[derive(Debug)]
28pub enum Frame<'a, 'id> {
29 Direct,
30 Prefixed {
31 prefix: &'a [u8],
32 remaining: scope::Range<'id>,
33 },
34}
35
36#[derive(Clone, Copy, Debug, Eq, PartialEq)]
37pub enum PrefixError {
38 Truncated {
39 actual: usize,
40 required: num::NonZero<usize>,
41 },
42 Unknown(u8),
43 Nested(u8),
44 Inner(u8),
45}
46
47impl Selector {
48 pub const fn fixed<
49 const BRANCH_AT: u8,
50 const BRANCH_MASK: u8,
51 const CLEAR_KEY: u8,
52 const CLEAR_MIN: u8,
53 const LENGTH_AT: u8,
54 const LENGTH: u8,
55 const SET_KEY: u8,
56 const SET_MIN: u8,
57 >() -> Self {
58 const {
59 assert!(BRANCH_MASK > 0);
60 assert!(BRANCH_AT < CLEAR_MIN);
61 assert!(CLEAR_KEY < CLEAR_MIN);
62 assert!(BRANCH_AT < SET_MIN);
63 assert!(LENGTH_AT < SET_MIN);
64 assert!(SET_KEY < SET_MIN);
65 assert!(CLEAR_MIN <= SET_MIN);
66 }
67 Self {
68 branch_at: BRANCH_AT,
69 branch_mask: num::NonZero::<u8>::MIN.saturating_add(BRANCH_MASK - 1),
70 clear_key: CLEAR_KEY,
71 clear_min: num::NonZero::<u8>::MIN.saturating_add(CLEAR_MIN - 1),
72 length_at: LENGTH_AT,
73 length: LENGTH,
74 set_key: SET_KEY,
75 set_min: num::NonZero::<u8>::MIN.saturating_add(SET_MIN - 1),
76 }
77 }
78
79 pub const fn branch_at(self) -> u8 {
80 self.branch_at
81 }
82
83 pub const fn branch_mask(self) -> num::NonZero<u8> {
84 self.branch_mask
85 }
86
87 pub const fn clear_key(self) -> u8 {
88 self.clear_key
89 }
90
91 pub const fn clear_min(self) -> num::NonZero<u8> {
92 self.clear_min
93 }
94
95 pub const fn length_at(self) -> u8 {
96 self.length_at
97 }
98
99 pub const fn length(self) -> u8 {
100 self.length
101 }
102
103 pub const fn set_key(self) -> u8 {
104 self.set_key
105 }
106
107 pub const fn set_min(self) -> num::NonZero<u8> {
108 self.set_min
109 }
110}
111
112impl PrefixPlan {
113 pub const fn fixed<const BYTES: u8, const RAW_MASK: u8, const FIRST: u8, const SECOND: u8>()
114 -> Self {
115 const {
116 assert!(BYTES > 0);
117 assert!(RAW_MASK > 0);
118 assert!(FIRST != SECOND);
119 assert!(FIRST & RAW_MASK == 0);
120 assert!(SECOND & RAW_MASK == 0);
121 }
122 Self {
123 extent: num::NonZero::<u8>::MIN.saturating_add(BYTES - 1),
124 raw_mask: num::NonZero::<u8>::MIN.saturating_add(RAW_MASK - 1),
125 tags: [FIRST, SECOND],
126 }
127 }
128
129 pub const fn extent(self) -> num::NonZero<u8> {
130 self.extent
131 }
132
133 pub const fn raw_mask(self) -> num::NonZero<u8> {
134 self.raw_mask
135 }
136
137 pub const fn tags(self) -> [u8; 2] {
138 self.tags
139 }
140
141 pub fn try_parse<'a, 'id>(
142 self,
143 source: scope::View<'a, 'id>,
144 ) -> Result<Frame<'a, 'id>, PrefixError> {
145 let packet = source.as_slice();
146 let first = *packet.first().ok_or(PrefixError::Truncated {
147 actual: 0,
148 required: num::NonZero::<usize>::MIN,
149 })?;
150 let raw_mask = self.raw_mask.get();
151 if first & raw_mask != 0 {
152 return Ok(Frame::Direct);
153 }
154 if !self.tags.contains(&first) {
155 return Err(PrefixError::Unknown(first));
156 }
157 let truncated = PrefixError::Truncated {
158 actual: packet.len(),
159 required: num::NonZero::<usize>::from(self.extent()).saturating_add(1),
160 };
161 let (prefix, packet, remaining) = source
162 .try_split_at(self.extent().into())
163 .map_err(|_| truncated)?;
164 let first = *packet.first().ok_or(truncated)?;
165 if self.tags.contains(&first) {
166 return Err(PrefixError::Nested(first));
167 }
168 if first & raw_mask == 0 {
169 return Err(PrefixError::Inner(first));
170 }
171 Ok(Frame::Prefixed { prefix, remaining })
172 }
173}
174
175const _: () = {
176 assert!(std::mem::size_of::<Selector>() == 8);
177 assert!(std::mem::align_of::<Selector>() == 1);
178 assert!(std::mem::size_of::<PrefixPlan>() == 4);
179 assert!(std::mem::align_of::<PrefixPlan>() == 1);
180};