1use crate::{DispatchError, DispatchResult, OpFrame};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct DenseOpArg {
9 pub n: i64,
11 pub text: &'static str,
13}
14
15impl DenseOpArg {
16 pub const ZERO: Self = Self { n: 0, text: "" };
18
19 pub const fn n(n: i64) -> Self { Self { n, text: "" } }
21
22 pub const fn text(text: &'static str) -> Self { Self { n: 0, text } }
24}
25
26pub type DenseOpFn = fn(OpFrame, DenseOpArg) -> DispatchResult<OpFrame>;
28
29#[derive(Clone, Copy)]
31pub struct DenseOpEntry {
32 pub func: DenseOpFn,
34 pub arg: DenseOpArg,
36 pub name: &'static str,
38}
39
40impl core::fmt::Debug for DenseOpEntry {
41 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
42 f.debug_struct("DenseOpEntry")
43 .field("name", &self.name)
44 .field("arg", &self.arg)
45 .finish()
46 }
47}
48
49pub fn dense_nop(frame: OpFrame, _arg: DenseOpArg) -> DispatchResult<OpFrame> { Ok(frame) }
51
52pub fn dense_add_prefix(mut frame: OpFrame, arg: DenseOpArg) -> DispatchResult<OpFrame> {
54 frame.text = format!("{}{}", arg.text, frame.text);
55 Ok(frame)
56}
57
58pub fn dense_add_suffix(mut frame: OpFrame, arg: DenseOpArg) -> DispatchResult<OpFrame> {
60 frame.text = format!("{}{}", frame.text, arg.text);
61 Ok(frame)
62}
63
64pub fn dense_acc_add(mut frame: OpFrame, arg: DenseOpArg) -> DispatchResult<OpFrame> {
66 frame.acc += arg.n;
67 Ok(frame)
68}
69
70pub fn dense_acc_mul(mut frame: OpFrame, arg: DenseOpArg) -> DispatchResult<OpFrame> {
72 frame.acc *= arg.n;
73 Ok(frame)
74}
75
76pub fn dense_octet_encode(mut frame: OpFrame, _arg: DenseOpArg) -> DispatchResult<OpFrame> {
78 if !frame.text.chars().all(|c| c.is_ascii_hexdigit()) {
79 return Err(DispatchError::InvalidInput(frame.text));
80 }
81 let value = u32::from_str_radix(&frame.text, 16)
82 .map_err(|_| DispatchError::InvalidInput(frame.text.clone()))?;
83 frame.text = format!("{:X}", value);
84 Ok(frame)
85}
86
87const NOP_ENTRY: DenseOpEntry = DenseOpEntry {
88 func: dense_nop,
89 arg: DenseOpArg::ZERO,
90 name: "nop",
91};
92
93#[derive(Debug, Clone)]
100pub struct DenseOperationTable {
101 entries: [DenseOpEntry; 256],
102}
103
104impl Default for DenseOperationTable {
105 fn default() -> Self { Self::new() }
106}
107
108impl DenseOperationTable {
109 pub fn new() -> Self { Self { entries: [NOP_ENTRY; 256] } }
111
112 pub fn register(&mut self, selector: u8, name: &'static str, func: DenseOpFn, arg: DenseOpArg) {
114 self.entries[selector as usize] = DenseOpEntry { func, arg, name };
115 }
116
117 pub fn execute(&self, selector: u8, frame: OpFrame) -> DispatchResult<OpFrame> {
119 let entry = self.entries[selector as usize];
120 (entry.func)(frame, entry.arg)
121 }
122
123 pub fn name(&self, selector: u8) -> &'static str { self.entries[selector as usize].name }
125}
126
127pub fn default_dense_table() -> DenseOperationTable {
129 let mut table = DenseOperationTable::new();
130 table.register(0x01, "add_prefix", dense_add_prefix, DenseOpArg::text("Prefix_"));
131 table.register(0x02, "add_suffix", dense_add_suffix, DenseOpArg::text("_Suffix"));
132 table.register(0x20, "octet_encode", dense_octet_encode, DenseOpArg::ZERO);
133 table.register(0x30, "acc_add", dense_acc_add, DenseOpArg::n(1));
134 table.register(0x31, "acc_mul", dense_acc_mul, DenseOpArg::n(2));
135 table
136}