Skip to main content

petr_dispatch/
builtins.rs

1use crate::{DispatchError, DispatchResult, OpArg, OpFrame, OperationTable};
2
3/// No-op operation.
4pub fn op_nop(frame: OpFrame, _arg: &OpArg) -> DispatchResult<OpFrame> { Ok(frame) }
5
6/// Prefix text.
7pub fn op_add_prefix(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
8    frame.text = format!("{}{}", arg.text, frame.text);
9    Ok(frame)
10}
11
12/// Suffix text.
13pub fn op_add_suffix(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
14    frame.text = format!("{}{}", frame.text, arg.text);
15    Ok(frame)
16}
17
18/// Add to accumulator.
19pub fn op_acc_add(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
20    frame.acc += arg.n;
21    Ok(frame)
22}
23
24/// Multiply accumulator.
25pub fn op_acc_mul(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
26    frame.acc *= arg.n;
27    Ok(frame)
28}
29
30/// Validate and multiply an octal string.
31pub fn op_octal_multiply(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
32    if !frame.text.chars().all(|c| c.is_digit(8)) {
33        return Err(DispatchError::InvalidInput(frame.text));
34    }
35    let value = u32::from_str_radix(&frame.text, 8).map_err(|_| DispatchError::InvalidInput(frame.text.clone()))?;
36    frame.text = format!("{:o}", value.saturating_mul(arg.n as u32));
37    Ok(frame)
38}
39
40/// Validate and add to an octal string.
41pub fn op_octal_add(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
42    if !frame.text.chars().all(|c| c.is_digit(8)) {
43        return Err(DispatchError::InvalidInput(frame.text));
44    }
45    let value = u32::from_str_radix(&frame.text, 8).map_err(|_| DispatchError::InvalidInput(frame.text.clone()))?;
46    frame.text = format!("{:o}", value.saturating_add(arg.n as u32));
47    Ok(frame)
48}
49
50/// Validate and normalize a hex/octet string.
51pub fn op_octet_encode(mut frame: OpFrame, _arg: &OpArg) -> DispatchResult<OpFrame> {
52    if !frame.text.chars().all(|c| c.is_ascii_hexdigit()) {
53        return Err(DispatchError::InvalidInput(frame.text));
54    }
55    let value = u32::from_str_radix(&frame.text, 16).map_err(|_| DispatchError::InvalidInput(frame.text.clone()))?;
56    frame.text = format!("{:X}", value);
57    Ok(frame)
58}
59
60/// Validate and add to a hex/octet string.
61pub fn op_octet_add(mut frame: OpFrame, arg: &OpArg) -> DispatchResult<OpFrame> {
62    if !frame.text.chars().all(|c| c.is_ascii_hexdigit()) {
63        return Err(DispatchError::InvalidInput(frame.text));
64    }
65    let value = u32::from_str_radix(&frame.text, 16).map_err(|_| DispatchError::InvalidInput(frame.text.clone()))?;
66    frame.text = format!("{:X}", value.saturating_add(arg.n as u32));
67    Ok(frame)
68}
69
70/// Install a useful default selector table.
71pub fn default_table() -> OperationTable {
72    let mut table = OperationTable::new();
73    table.register(0x00, "nop", op_nop, OpArg::default());
74    table.register(0x01, "add_prefix", op_add_prefix, OpArg::text("Prefix_"));
75    table.register(0x02, "add_suffix", op_add_suffix, OpArg::text("_Suffix"));
76    table.register(0x10, "octal_multiply", op_octal_multiply, OpArg::n(2));
77    table.register(0x11, "octal_add", op_octal_add, OpArg::n(1));
78    table.register(0x20, "octet_encode", op_octet_encode, OpArg::default());
79    table.register(0x21, "octet_add", op_octet_add, OpArg::n(1));
80    table.register(0x30, "acc_add", op_acc_add, OpArg::n(1));
81    table.register(0x31, "acc_mul", op_acc_mul, OpArg::n(2));
82    table
83}