Skip to main content

petr_dispatch/
typed.rs

1use petr_core::SelectorWord;
2
3/// Function pointer used by a typed dense operation table.
4///
5/// Unlike [`crate::OperationTable`], this form is not coupled to `OpFrame`.
6/// It can mutate an application-owned state value while reading an immutable
7/// execution context.
8pub type TypedDenseOpFn<State, Context, Error> =
9    fn(&mut State, &Context) -> Result<(), Error>;
10
11/// Fixed 256-slot selector table for application-specific state machines.
12///
13/// Every slot is initialized with the caller-provided fallback operation. The
14/// hot path is therefore a selector-indexed function-pointer call without an
15/// `Option` lookup. This is still an indirect branch at the CPU level.
16pub struct TypedDenseOperationTable<State, Context, Error> {
17    entries: [TypedDenseOpFn<State, Context, Error>; 256],
18}
19
20impl<State, Context, Error> core::fmt::Debug
21    for TypedDenseOperationTable<State, Context, Error>
22{
23    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24        f.debug_struct("TypedDenseOperationTable")
25            .field("slots", &self.entries.len())
26            .finish()
27    }
28}
29
30impl<State, Context, Error> Clone
31    for TypedDenseOperationTable<State, Context, Error>
32{
33    fn clone(&self) -> Self {
34        Self { entries: self.entries }
35    }
36}
37
38impl<State, Context, Error> TypedDenseOperationTable<State, Context, Error> {
39    /// Create a table with all selectors bound to `fallback`.
40    pub fn new(fallback: TypedDenseOpFn<State, Context, Error>) -> Self {
41        Self { entries: [fallback; 256] }
42    }
43
44    /// Register an application operation at a raw byte selector.
45    pub fn register(
46        &mut self,
47        selector: u8,
48        operation: TypedDenseOpFn<State, Context, Error>,
49    ) {
50        self.entries[selector as usize] = operation;
51    }
52
53    /// Register using the function byte of a 4/4/8 selector word.
54    pub fn register_word(
55        &mut self,
56        selector: SelectorWord,
57        operation: TypedDenseOpFn<State, Context, Error>,
58    ) {
59        self.register(selector.function_id(), operation);
60    }
61
62    /// Execute by raw selector.
63    pub fn execute(
64        &self,
65        selector: u8,
66        state: &mut State,
67        context: &Context,
68    ) -> Result<(), Error> {
69        (self.entries[selector as usize])(state, context)
70    }
71
72    /// Execute using the function byte of a selector word.
73    pub fn execute_word(
74        &self,
75        selector: SelectorWord,
76        state: &mut State,
77        context: &Context,
78    ) -> Result<(), Error> {
79        self.execute(selector.function_id(), state, context)
80    }
81}