Skip to main content

dope_sys/io/socket/route/
selector.rs

1use std::num;
2
3use o3::buffer::bytes::scope;
4
5/// Selects one dense route byte from either of two packet shapes.
6#[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/// Hashes a bounded variable key when the set shape has no direct route.
19/// Zero versions retain strict routing; unmatched nonzero versions select route zero.
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
21pub struct Bootstrap {
22    version: num::NonZero<u32>,
23    version_at: u8,
24    mask: num::NonZero<u8>,
25    value: u8,
26    min: num::NonZero<u8>,
27    max: num::NonZero<u8>,
28}
29
30/// An optional fixed prefix whose tags cannot be mistaken for a direct packet.
31#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32pub struct PrefixPlan {
33    extent: num::NonZero<u8>,
34    raw_mask: num::NonZero<u8>,
35    tags: [u8; 2],
36}
37
38/// A borrowed prefix and the remaining range bound to its original datagram.
39#[derive(Debug)]
40pub enum Frame<'a, 'id> {
41    Direct,
42    Prefixed {
43        prefix: &'a [u8],
44        remaining: scope::Range<'id>,
45    },
46}
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum PrefixError {
50    Truncated {
51        actual: usize,
52        required: num::NonZero<usize>,
53    },
54    Unknown(u8),
55    Nested(u8),
56    Inner(u8),
57}
58
59impl Selector {
60    pub const fn fixed<
61        const BRANCH_AT: u8,
62        const BRANCH_MASK: u8,
63        const CLEAR_KEY: u8,
64        const CLEAR_MIN: u8,
65        const LENGTH_AT: u8,
66        const LENGTH: u8,
67        const SET_KEY: u8,
68        const SET_MIN: u8,
69    >() -> Self {
70        const {
71            assert!(BRANCH_MASK > 0);
72            assert!(BRANCH_AT < CLEAR_MIN);
73            assert!(CLEAR_KEY < CLEAR_MIN);
74            assert!(BRANCH_AT < SET_MIN);
75            assert!(LENGTH_AT < SET_MIN);
76            assert!(SET_KEY < SET_MIN);
77            assert!(CLEAR_MIN <= SET_MIN);
78        }
79        Self {
80            branch_at: BRANCH_AT,
81            branch_mask: num::NonZero::<u8>::MIN.saturating_add(BRANCH_MASK - 1),
82            clear_key: CLEAR_KEY,
83            clear_min: num::NonZero::<u8>::MIN.saturating_add(CLEAR_MIN - 1),
84            length_at: LENGTH_AT,
85            length: LENGTH,
86            set_key: SET_KEY,
87            set_min: num::NonZero::<u8>::MIN.saturating_add(SET_MIN - 1),
88        }
89    }
90
91    pub const fn branch_at(self) -> u8 {
92        self.branch_at
93    }
94
95    pub const fn branch_mask(self) -> num::NonZero<u8> {
96        self.branch_mask
97    }
98
99    pub const fn clear_key(self) -> u8 {
100        self.clear_key
101    }
102
103    pub const fn clear_min(self) -> num::NonZero<u8> {
104        self.clear_min
105    }
106
107    pub const fn length_at(self) -> u8 {
108        self.length_at
109    }
110
111    pub const fn length(self) -> u8 {
112        self.length
113    }
114
115    pub const fn set_key(self) -> u8 {
116        self.set_key
117    }
118
119    pub const fn set_min(self) -> num::NonZero<u8> {
120        self.set_min
121    }
122}
123
124impl Bootstrap {
125    /// Native variable-key capacity, independent of the caller's wire format.
126    pub const MAX: u8 = 20;
127
128    /// Matches a network-order version and the selector's masked branch byte.
129    /// Hash input is the declared length followed by bytes at `Selector::set_key`.
130    pub const fn fixed<
131        const VERSION_AT: u8,
132        const VERSION: u32,
133        const MASK: u8,
134        const VALUE: u8,
135        const MIN: u8,
136        const MAX: u8,
137    >() -> Self {
138        const {
139            assert!(VERSION > 0);
140            assert!(MASK > 0 && VALUE & !MASK == 0);
141            assert!(MIN > 0 && MIN <= MAX && MAX <= Bootstrap::MAX);
142        }
143        Self {
144            version: num::NonZero::<u32>::MIN.saturating_add(VERSION - 1),
145            version_at: VERSION_AT,
146            mask: num::NonZero::<u8>::MIN.saturating_add(MASK - 1),
147            value: VALUE,
148            min: num::NonZero::<u8>::MIN.saturating_add(MIN - 1),
149            max: num::NonZero::<u8>::MIN.saturating_add(MAX - 1),
150        }
151    }
152
153    pub const fn version(self) -> num::NonZero<u32> {
154        self.version
155    }
156
157    pub const fn version_at(self) -> u8 {
158        self.version_at
159    }
160
161    pub const fn mask(self) -> num::NonZero<u8> {
162        self.mask
163    }
164
165    pub const fn value(self) -> u8 {
166        self.value
167    }
168
169    pub const fn min(self) -> num::NonZero<u8> {
170        self.min
171    }
172
173    pub const fn max(self) -> num::NonZero<u8> {
174        self.max
175    }
176}
177
178impl PrefixPlan {
179    pub const fn fixed<const BYTES: u8, const RAW_MASK: u8, const FIRST: u8, const SECOND: u8>()
180    -> Self {
181        const {
182            assert!(BYTES > 0);
183            assert!(RAW_MASK > 0);
184            assert!(FIRST != SECOND);
185            assert!(FIRST & RAW_MASK == 0);
186            assert!(SECOND & RAW_MASK == 0);
187        }
188        Self {
189            extent: num::NonZero::<u8>::MIN.saturating_add(BYTES - 1),
190            raw_mask: num::NonZero::<u8>::MIN.saturating_add(RAW_MASK - 1),
191            tags: [FIRST, SECOND],
192        }
193    }
194
195    pub const fn extent(self) -> num::NonZero<u8> {
196        self.extent
197    }
198
199    pub const fn raw_mask(self) -> num::NonZero<u8> {
200        self.raw_mask
201    }
202
203    pub const fn tags(self) -> [u8; 2] {
204        self.tags
205    }
206
207    pub fn try_parse<'a, 'id>(
208        self,
209        source: scope::View<'a, 'id>,
210    ) -> Result<Frame<'a, 'id>, PrefixError> {
211        let packet = source.as_slice();
212        let first = *packet.first().ok_or(PrefixError::Truncated {
213            actual: 0,
214            required: num::NonZero::<usize>::MIN,
215        })?;
216        let raw_mask = self.raw_mask.get();
217        if first & raw_mask != 0 {
218            return Ok(Frame::Direct);
219        }
220        if !self.tags.contains(&first) {
221            return Err(PrefixError::Unknown(first));
222        }
223        let truncated = PrefixError::Truncated {
224            actual: packet.len(),
225            required: num::NonZero::<usize>::from(self.extent()).saturating_add(1),
226        };
227        let (prefix, packet, remaining) = source
228            .try_split_at(self.extent().into())
229            .map_err(|_| truncated)?;
230        let first = *packet.first().ok_or(truncated)?;
231        if self.tags.contains(&first) {
232            return Err(PrefixError::Nested(first));
233        }
234        if first & raw_mask == 0 {
235            return Err(PrefixError::Inner(first));
236        }
237        Ok(Frame::Prefixed { prefix, remaining })
238    }
239}
240
241const _: () = {
242    assert!(std::mem::size_of::<Selector>() == 8);
243    assert!(std::mem::align_of::<Selector>() == 1);
244    assert!(std::mem::size_of::<PrefixPlan>() == 4);
245    assert!(std::mem::align_of::<PrefixPlan>() == 1);
246};