Diffstat (limited to 'src/lib_old.rs')
-rw-r--r--src/lib_old.rs424
1 files changed, 424 insertions, 0 deletions
diff --git a/src/lib_old.rs b/src/lib_old.rs
new file mode 100644
index 0000000..90bf7f4
--- /dev/null
+++ b/src/lib_old.rs
@@ -0,0 +1,424 @@
+pub mod recognizer;
+pub mod v2;
+mod utf8;
+
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+/// A control sequence parameter.
+pub enum Parameter {
+ /// A for the control sequence appropriate default value should be used.
+ Default,
+ /// The parameter has a value.
+ Value(u16)
+}
+
+impl Parameter {
+ pub fn new(v: u16) -> Self {
+ Self::Value(v)
+ }
+
+ /// Returns the value of the parameter, if present, otherwise returns the given default.
+ pub fn value_or(&self, or: u16) -> u16 {
+ match self {
+ Self::Default => or,
+ Self::Value(v) => *v,
+ }
+ }
+
+ /// Parsing parameters requires an [`atoi`]-like loop.
+ ///
+ /// Parameter value overflow causes the sequence to be rejected.
+ ///
+ /// [`atoi`]: https://en.cppreference.com/w/c/string/byte/atoi
+ pub fn add(&mut self, x: u16) -> bool {
+ match self {
+ Self::Default => {
+ *self = Self::Value(x);
+ false
+ },
+
+ Self::Value(v) => {
+ let (v2, oflw) = v.overflowing_add(x);
+ *v = v2;
+ oflw
+ }
+ }
+ }
+}
+
+impl Default for Parameter {
+ fn default() -> Self {
+ Self::Default
+ }
+}
+
+#[derive(Clone, Eq, PartialEq, Debug, Default)]
+pub struct ControlFunction {
+ /// The start of the control function.
+ ///
+ /// For C0 and C1 controls, which are only 1 byte,
+ /// this is the only necessary field.
+ start: u8,
+ /// Whether this control sequence has a private parameter string.
+ private: bool,
+ /// The parameters of the control sequence, if it is one.
+ params: Vec<Parameter>,
+ /// If this function is a control string,
+ /// this is the string's content.
+ ///
+ /// Otherwise, it's the intermediate bytes of the function.
+ /// For control sequences with private parameters, this contains the raw parameter string.
+ bytes: Vec<u8>,
+ /// The final byte of the control function.
+ ///
+ /// For C0 and C1 controls, as well as control strings,
+ /// this field is left unset.
+ end: u8,
+}
+
+#[derive(Clone, Eq, PartialEq, Debug)]
+pub enum TerminalInput<'a> {
+ Continue,
+ Char(char),
+ // FIXME: Passing this by reference saves on allocations,
+ // but currently requires that it is fully processed before parsing can continue.
+ // For performance, it may be better to pass a clone by value, and use a queue to avoid
+ // the input buffer getting clogged. Relevant for stuff that may take longer to evaluate,
+ // like SIXEL strings.
+ // Will require benchmarking though.
+ Control(&'a ControlFunction),
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct TerminalInputParser {
+ /// The current parsing state.
+ state: State,
+ /// Container for parsed control function data.
+ ctl: ControlFunction,
+ /// Accumulator for current control sequence parameter.
+ pacc: Parameter,
+ // /// UTF-8 character decoder.
+ // utf8: UTF8Decoder
+}
+
+impl TerminalInputParser {
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ pub fn parse_byte(&mut self, byte: u8) -> TerminalInput {
+
+ unimplemented!()
+ }
+}
+
+
+
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+enum Class {
+ /// C0 Control Functions
+ ///
+ /// 00..1F
+ C0,
+
+ /// C0 Control Functions permitted in Control Strings
+ ///
+ /// 08..0D
+ C0S,
+
+ /// ESCAPE
+ ///
+ /// 1B
+ ESC,
+
+ /// Control Function / Control Sequence Intermediate Bytes
+ ///
+ /// 20..2F
+ INT,
+
+ /// Control Sequence Parameter Bytes
+ ///
+ /// 30..39
+ PAR,
+
+ /// Control Sequence Parameter Separators
+ ///
+ /// 3A..3B
+ SEP,
+
+ /// Control Sequence Private Parameter String Indicator
+ ///
+ /// 3C..3F
+ PRI,
+
+ /// C1 Control Functions
+ ///
+ /// ESC 40..5F
+ C1,
+
+ /// Command String Opening Delimiter
+ ///
+ /// ESC 50, ESC 5D..5F
+ CSO,
+
+ /// Start Of String
+ ///
+ /// ESC 58
+ SOS,
+
+ /// Single Character Introducer
+ ///
+ /// ESC 5A
+ SCI,
+
+ /// Control Sequence Introducer
+ ///
+ /// ESC 5B
+ CSI,
+
+ /// String Terminator
+ ///
+ /// ESC 5C
+ ST,
+
+ /// Independent Control Function Final Bytes
+ ///
+ /// 60..7E
+ ICF,
+
+ /// DELETE
+ ///
+ /// 7F
+ DEL,
+}
+
+use Class::*;
+
+/// Byte to Class translation table
+const CLASS_TABLE: [Class; 128] = [
+ C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0S,C0S,C0S,C0S,C0S,C0S,C0 ,C0 ,
+ C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,C0 ,ESC,C0 ,C0 ,C0 ,C0 ,
+ INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,INT,
+ PAR,PAR,PAR,PAR,PAR,PAR,PAR,PAR,PAR,PAR,SEP,SEP,PRI,PRI,PRI,PRI,
+ C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,
+ CSO,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,C1 ,SOS,C1 ,SCI,CSI,ST ,CSO,CSO,CSO,
+ ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,
+ ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,ICF,DEL,
+];
+
+/// State + Class to State transition table
+const STATE_TABLE: [State; 185] = [State::OK;185];
+
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+enum Action {
+ Continue,
+ ReturnChar,
+ C01Control,
+ StartSequence,
+ FinishSequence,
+ PushByte,
+ SetPrivate,
+ PushLastParam,
+ PushParamAndByte,
+ PushParam,
+ AddParamValue,
+}
+
+#[allow(non_camel_case_types)]
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+// NCB: 20..7E
+// CFF: 30..7E
+// CSC: 08..0D,20..7E
+
+// 11 unique actions
+// return char
+// return continue
+// set start, return control
+// set start, return continue
+// set end, return control
+// push byte, return continue
+// set private, return continue
+// push param, set end, return control
+// push param, push byte, return continue
+// push param, return continue
+// add value, return continue
+
+// always return to some base state, which is a multiple of 15
+// for example, we will never match against state 61
+// use modulo 15 arithmetic to encode 61 as "action 1, state 60"
+// modulo 15 not ideal
+// pad rows to 16 so we can use modulo 16 (easy bitmask)
+
+
+
+enum State {
+ /// Base state
+ ///
+ /// ```text,ignore
+ /// C0 -> OK_C01 (set start, return control)
+ /// ESC -> ESC (set start, return continue)
+ /// NCB -> OK_NCB ( return char)
+ /// DEL -> OK ( return continue)
+ /// ```
+ OK = 0x00,
+
+ /// Received ESCAPE
+ ///
+ /// ```text,ignore
+ /// C0 -> OK_C01 (set start, return control)
+ /// INT -> CF (push byte, return continue)
+ /// CFF -> OK_CF (set end, return control)
+ /// C1 -> OK_C01 (set start, return control)
+ /// CSO -> CMS (set start, return continue)
+ /// SOS -> SOS (set start, return continue)
+ /// SCI -> SCI (set start, return continue)
+ /// CSI -> CSI (set start, return continue)
+ /// _ -> OK ( return continue)
+ /// ```
+ ESC = 0x10,
+
+ /// Control Function
+ ///
+ /// ```text,ignore
+ /// INT -> CF (push byte, return continue)
+ /// CFF -> OK_CF (set end, return control)
+ /// _ -> ERR_CF ( return continue)
+ /// ```
+ CF = 0x20,
+
+ /// Poisoned Control Function
+ ///
+ /// ```text,ignore
+ /// CFF -> OK (return continue)
+ /// _ -> ERR_CF (return continue)
+ /// ```
+ ERR_CF = 0x30,
+
+ /// Command String
+ ///
+ /// ```text,ignore
+ /// ESC -> CMS_ESC ( return continue)
+ /// CSC -> CMS_ACC (push byte, return continue)
+ /// _ -> ERR_CMS ( return continue)
+ /// ```
+ CMS = 0x40,
+
+ /// Command String, Received ESCAPE
+ ///
+ /// ```text,ignore
+ /// ST -> OK_CF (set end, return control)
+ /// _ -> ERR_CMS ( return continue)
+ /// ```
+ CMS_ESC = 0x50,
+
+ /// Poisoned Command String
+ ///
+ /// ```text,ignore
+ /// ESC -> CMS_ESC (return continue)
+ /// _ -> ERR_CMS (return continue)
+ /// ```
+ ERR_CMS = 0x60,
+
+ /// Start Of String
+ ///
+ /// ```text,ignore
+ /// ESC -> SOS_ESC ( return continue)
+ /// _ -> SOS_ACC (push byte, return continue)
+ /// ```
+ SOS = 0x70,
+
+ /// Start Of String, Received ESCAPE
+ ///
+ /// ```text,ignore
+ /// ST -> OK_CF (set end, return control)
+ /// SOS -> ERR_CMS ( return continue)
+ /// _ -> SOS_ACC (push byte, return continue)
+ /// ```
+ SOS_ESC = 0x80,
+
+ /// Single Character Introducer
+ ///
+ /// ```text,ignore
+ /// CSC -> OK_CF (set end, return control)
+ /// _ -> OK ( return continue)
+ /// ```
+ SCI = 0x90,
+
+ /// Control Sequence Introducer
+ ///
+ /// ```text,ignore
+ /// PRI -> CSI_PRI (set private, return continue)
+ /// PAR -> CSI_PAR (add value, return continue)
+ /// SEP -> CSI_SEP (push param, return continue)
+ /// INT -> CSI_INT (push byte, return continue)
+ /// CSF -> OK_CF (set end, return control)
+ /// _ -> ERR_CSI ( return continue)
+ /// ```
+ CSI = 0xA0,
+
+ /// Control Sequence Introducer, Received Parameter Byte
+ ///
+ /// ```text,ignore
+ /// PAR -> CSI_PAR (add value, return continue)
+ /// SEP -> CSI_SEP (push param, return continue)
+ /// INT -> CSI_PIN (push param, push byte, return continue)
+ /// CSF -> OK_CSI (push param, set end, return control)
+ /// _ -> ERR_CSI ( return continue)
+ /// ```
+ CSI_PAR = 0xB0,
+
+ /// Control Sequence Introducer, Received Intermediate Byte
+ ///
+ /// ```text,ignore
+ /// INT -> CSI_INT (push byte, return continue)
+ /// CSF -> OK_CF (set end, return control)
+ /// _ -> ERR_CSI ( return continue)
+ /// ```
+ CSI_INT = 0xC0,
+
+ /// Poisoned Control Sequence Introducer
+ ///
+ /// ```text,ignore
+ /// CSF -> OK (return continue)
+ /// _ -> ERR_CSI (return continue)
+ /// ```
+ ERR_CSI = 0xD0,
+
+ // All states with an action.
+ // Base states are implicitly Action::Continue.
+ OK_C01 = State::OK as u8 | Action::C01Control as u8,
+ OK_NCB = State::OK as u8 | Action::ReturnChar as u8,
+ TR_ESC = State::ESC as u8 | Action::StartSequence as u8,
+ TR_CF = State::CF as u8 | Action::PushByte as u8,
+ OK_CF = State::OK as u8 | Action::FinishSequence as u8,
+ TR_CMS = State::CMS as u8 | Action::StartSequence as u8,
+ TR_SOS = State::SOS as u8 | Action::StartSequence as u8,
+ TR_SCI = State::SCI as u8 | Action::StartSequence as u8,
+ TR_CSI = State::CSI as u8 | Action::StartSequence as u8,
+ CMS_ACC = State::CMS as u8 | Action::PushByte as u8,
+ SOS_ACC = State::SOS as u8 | Action::PushByte as u8,
+ CSI_PRI = State::CSI as u8 | Action::SetPrivate as u8,
+ CSI_SEP = State::CSI as u8 | Action::PushParam as u8,
+ CSI_PAC = State::CSI as u8 | Action::AddParamValue as u8,
+ CSI_IAC = State::CSI as u8 | Action::PushByte as u8,
+ CSI_PIN = State::CSI as u8 | Action::PushParamAndByte as u8,
+}
+
+impl State {
+ /// Decomposes a state into base state and parser action.
+ fn decompose(self) -> (State, Action) {
+ use std::mem::transmute as cast;
+
+ unsafe {
+ (cast(self as u8 & 0xF0), cast(self as u8 & 0x0F))
+ }
+ }
+}
+
+impl Default for State {
+ fn default() -> State {
+ State::OK
+ }
+}