Skip to main content

petr_dispatch/
shuffle.rs

1use crate::{DispatchResult, OpFrame, OperationTable};
2
3/// A boot/session-local permutation over 256 bytecode selectors.
4#[derive(Debug, Clone)]
5pub struct SelectorPermutation {
6    logical_to_physical: [u8; 256],
7    physical_to_logical: [u8; 256],
8}
9
10impl SelectorPermutation {
11    /// Create a deterministic shuffled permutation from a seed.
12    pub fn from_seed(seed: u64) -> Self {
13        let mut arr = [0u8; 256];
14        let mut i = 0usize;
15        while i < 256 {
16            arr[i] = i as u8;
17            i += 1;
18        }
19        let mut x = seed;
20        let mut j = 255usize;
21        while j > 0 {
22            x ^= x << 13;
23            x ^= x >> 7;
24            x ^= x << 17;
25            let k = (x as usize) % (j + 1);
26            arr.swap(j, k);
27            j -= 1;
28        }
29        let mut inv = [0u8; 256];
30        for (logical, physical) in arr.iter().enumerate() {
31            inv[*physical as usize] = logical as u8;
32        }
33        Self { logical_to_physical: arr, physical_to_logical: inv }
34    }
35
36    /// Encode a logical selector into the shuffled physical selector.
37    pub fn encode(&self, logical: u8) -> u8 { self.logical_to_physical[logical as usize] }
38
39    /// Decode a physical selector back to the logical selector.
40    pub fn decode(&self, physical: u8) -> u8 { self.physical_to_logical[physical as usize] }
41}
42
43/// Operation table whose externally visible bytecode selectors are shuffled.
44#[derive(Debug, Clone)]
45pub struct ShuffledOperationTable {
46    table: OperationTable,
47    permutation: SelectorPermutation,
48}
49
50impl ShuffledOperationTable {
51    /// Create a shuffled table from an existing logical table.
52    pub fn new(logical: OperationTable, seed: u64) -> Self {
53        Self { table: logical, permutation: SelectorPermutation::from_seed(seed) }
54    }
55
56    /// Encode logical selector for storage/transmission.
57    pub fn encode_selector(&self, logical: u8) -> u8 { self.permutation.encode(logical) }
58
59    /// Execute using a shuffled physical selector.
60    pub fn execute_physical(&self, physical: u8, frame: OpFrame) -> DispatchResult<OpFrame> {
61        let logical = self.permutation.decode(physical);
62        self.table.execute(logical, frame)
63    }
64}