use std::mem::transmute;
pub fn query(from_state: State, byte: u8) -> (Action, State) {
let table_value = TABLE[from_state as usize][byte as usize];
let to_action: Action = unsafe { transmute((table_value & 0xF0) >> 4) };
let to_state: State = unsafe { transmute(table_value & 0x0F) };
(to_action, to_state)
}
const TABLE: [[u8; 256]; 16] = build_state_table();
const fn build_state_table() -> [[u8; 256]; 16] {
let mut table = [[0u8; 256]; 16];
let mut state_index = 0;
while state_index < STATES.len() {
let from_state = STATES[state_index];
let mut i: usize = 0;
while i <= 0xFF {
let (to_action, to_state) = table_fn(from_state, i as u8);
let value = ((to_action as u8) << 4) | (to_state as u8);
table[from_state as usize][i] = value;
i += 1;
}
state_index += 1;
}
table
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u8)]
pub enum State {
CsiEntry = 0,
CsiIgnore = 1,
CsiIntermediate = 2,
CsiParam = 3,
DcsEntry = 4,
DcsIgnore = 5,
DcsIntermediate = 6,
DcsParam = 7,
DcsPassthrough = 8,
Error = 9,
Escape = 10,
EscapeIntermediate = 11,
Ground = 12,
OscString = 13,
SosPmApcString = 14,
}
const STATES: &[State] = &[
State::CsiEntry,
State::CsiIgnore,
State::CsiIntermediate,
State::CsiParam,
State::DcsEntry,
State::DcsIgnore,
State::DcsIntermediate,
State::DcsParam,
State::DcsPassthrough,
State::Error,
State::Escape,
State::EscapeIntermediate,
State::Ground,
State::OscString,
State::SosPmApcString,
];
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u8)]
pub enum Action {
None = 0,
Clear = 1,
Collect = 2,
CsiDispatch = 3,
EscDispatch = 4,
Execute = 5,
Hook = 6,
Ignore = 7,
OscEnd = 8,
OscPut = 9,
OscStart = 10,
Param = 11,
Print = 12,
Put = 13,
Unhook = 14,
}
pub static ENTRY_ACTIONS: &[Action] = &[
Action::Clear, Action::None, Action::None, Action::None, Action::Clear, Action::None, Action::None, Action::None, Action::Hook, Action::None, Action::Clear, Action::None, Action::None, Action::OscStart, Action::None, ];
pub static EXIT_ACTIONS: &[Action] = &[
Action::None, Action::None, Action::None, Action::None, Action::None, Action::None, Action::None, Action::None, Action::Unhook, Action::None, Action::None, Action::None, Action::None, Action::OscEnd, Action::None, ];
#[rustfmt::skip]
pub static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, ];
const fn table_fn(state: State, byte: u8) -> (Action, State) {
match (state, byte) {
(_, 0x18) => (Action::Execute, State::Ground),
(_, 0x1A) => (Action::Execute, State::Ground),
(_, 0x80..=0x8F) => (Action::Execute, State::Ground),
(_, 0x91..=0x97) => (Action::Execute, State::Ground),
(_, 0x99) => (Action::Execute, State::Ground),
(_, 0x9A) => (Action::Execute, State::Ground),
(_, 0x9C) => (Action::None, State::Ground),
(_, 0x1B) => (Action::None, State::Escape),
(_, 0x98) => (Action::None, State::SosPmApcString),
(_, 0x9E) => (Action::None, State::SosPmApcString),
(_, 0x9F) => (Action::None, State::SosPmApcString),
(_, 0x90) => (Action::None, State::DcsEntry),
(_, 0x9D) => (Action::None, State::OscString),
(_, 0x9B) => (Action::None, State::CsiEntry),
(State::CsiEntry, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::CsiEntry),
0x19 => (Action::Execute, State::CsiEntry),
0x1C..=0x1F => (Action::Execute, State::CsiEntry),
0x7F => (Action::Ignore, State::CsiEntry),
0x30..=0x39 => (Action::Param, State::CsiParam),
0x3C..=0x3F => (Action::Collect, State::CsiParam),
0x3A => (Action::None, State::CsiIgnore),
0x20..=0x2F => (Action::Collect, State::CsiIntermediate),
0x40..=0x7E => (Action::CsiDispatch, State::Ground),
_ => (Action::None, State::Error),
},
(State::CsiIgnore, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::CsiIgnore),
0x19 => (Action::Execute, State::CsiIgnore),
0x1C..=0x1F => (Action::Execute, State::CsiIgnore),
0x20..=0x3F => (Action::Ignore, State::CsiIgnore),
0x7F => (Action::Ignore, State::CsiIgnore),
0x40..=0x7E => (Action::None, State::Ground),
_ => (Action::None, State::Error),
},
(State::CsiIntermediate, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::CsiIntermediate),
0x19 => (Action::Execute, State::CsiIntermediate),
0x1C..=0x1F => (Action::Execute, State::CsiIntermediate),
0x20..=0x2F => (Action::Collect, State::CsiIntermediate),
0x7F => (Action::Ignore, State::CsiIntermediate),
0x40..=0x7E => (Action::CsiDispatch, State::Ground),
_ => (Action::None, State::Error),
},
(State::CsiParam, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::CsiParam),
0x19 => (Action::Execute, State::CsiParam),
0x1C..=0x1F => (Action::Execute, State::CsiParam),
0x30..=0x39 => (Action::Param, State::CsiParam),
0x3B => (Action::Param, State::CsiParam),
0x7F => (Action::Ignore, State::CsiParam),
0x40..=0x7E => (Action::CsiDispatch, State::Ground),
0x20..=0x2F => (Action::Collect, State::CsiIntermediate),
0x3A => (Action::None, State::CsiIgnore),
0x3C..=0x3F => (Action::None, State::CsiIgnore),
_ => (Action::None, State::Error),
},
(State::DcsEntry, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::DcsEntry),
0x19 => (Action::Ignore, State::DcsEntry),
0x1C..=0x1F => (Action::Ignore, State::DcsEntry),
0x7F => (Action::Ignore, State::DcsEntry),
0x20..=0x2F => (Action::Collect, State::DcsIntermediate),
0x3A => (Action::None, State::DcsIgnore),
0x30..=0x39 => (Action::Param, State::DcsParam),
0x3C..=0x3F => (Action::Collect, State::DcsParam),
0x40..=0x7E => (Action::None, State::DcsPassthrough),
_ => (Action::None, State::Error),
},
(State::DcsIgnore, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::DcsIgnore),
0x19 => (Action::Ignore, State::DcsIgnore),
0x1C..=0x1F => (Action::Ignore, State::DcsIgnore),
0x20..=0x7F => (Action::Ignore, State::DcsIgnore),
_ => (Action::None, State::Error),
},
(State::DcsIntermediate, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::DcsIntermediate),
0x19 => (Action::Ignore, State::DcsIntermediate),
0x1C..=0x1F => (Action::Ignore, State::DcsIntermediate),
0x20..=0x2F => (Action::Collect, State::DcsIntermediate),
0x7F => (Action::Ignore, State::DcsIntermediate),
0x40..=0x7E => (Action::None, State::DcsPassthrough),
0x30..=0x3F => (Action::None, State::DcsIgnore),
_ => (Action::None, State::Error),
},
(State::DcsParam, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::DcsParam),
0x19 => (Action::Ignore, State::DcsParam),
0x1C..=0x1F => (Action::Ignore, State::DcsParam),
0x30..=0x39 => (Action::Param, State::DcsParam),
0x3B => (Action::Param, State::DcsParam),
0x7F => (Action::Ignore, State::DcsParam),
0x3A => (Action::None, State::DcsIgnore),
0x3C..=0x3F => (Action::None, State::DcsIgnore),
0x20..=0x2F => (Action::Collect, State::DcsIntermediate),
0x40..=0x7E => (Action::None, State::DcsPassthrough),
_ => (Action::None, State::Error),
},
(State::DcsPassthrough, byte) => match byte {
0x00..=0x17 => (Action::Put, State::DcsPassthrough),
0x19 => (Action::Put, State::DcsPassthrough),
0x1C..=0x1F => (Action::Put, State::DcsPassthrough),
0x20..=0x7E => (Action::Put, State::DcsPassthrough),
0x7F => (Action::Ignore, State::DcsPassthrough),
_ => (Action::None, State::Error),
},
(State::Error, _) => (Action::None, State::Error),
(State::Escape, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::Escape),
0x19 => (Action::Execute, State::Escape),
0x1C..=0x1F => (Action::Execute, State::Escape),
0x7F => (Action::Ignore, State::Escape),
0x20..=0x2F => (Action::Collect, State::EscapeIntermediate),
0x30..=0x4F => (Action::EscDispatch, State::Ground),
0x51..=0x57 => (Action::EscDispatch, State::Ground),
0x59 => (Action::EscDispatch, State::Ground),
0x5A => (Action::EscDispatch, State::Ground),
0x5C => (Action::EscDispatch, State::Ground),
0x60..=0x7E => (Action::EscDispatch, State::Ground),
0x5B => (Action::None, State::CsiEntry),
0x5D => (Action::None, State::OscString),
0x50 => (Action::None, State::DcsEntry),
0x58 => (Action::None, State::SosPmApcString),
0x5E => (Action::None, State::SosPmApcString),
0x5F => (Action::None, State::SosPmApcString),
_ => (Action::None, State::Error),
},
(State::EscapeIntermediate, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::EscapeIntermediate),
0x19 => (Action::Execute, State::EscapeIntermediate),
0x1C..=0x1F => (Action::Execute, State::EscapeIntermediate),
0x20..=0x2F => (Action::Collect, State::EscapeIntermediate),
0x7F => (Action::Ignore, State::EscapeIntermediate),
0x30..=0x7E => (Action::EscDispatch, State::Ground),
_ => (Action::None, State::Error),
},
(State::Ground, byte) => match byte {
0x00..=0x17 => (Action::Execute, State::Ground),
0x19 => (Action::Execute, State::Ground),
0x1C..=0x1F => (Action::Execute, State::Ground),
0x20..=0x7F => (Action::Print, State::Ground),
0xC0..=0xDF => (Action::Print, State::Ground),
0xE0..=0xEF => (Action::Print, State::Ground),
0xF0..=0xF7 => (Action::Print, State::Ground),
_ => (Action::None, State::Error),
},
(State::OscString, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::OscString),
0x19 => (Action::Ignore, State::OscString),
0x1C..=0x1F => (Action::Ignore, State::OscString),
0x20..=0x7F => (Action::OscPut, State::OscString),
_ => (Action::None, State::Error),
},
(State::SosPmApcString, byte) => match byte {
0x00..=0x17 => (Action::Ignore, State::SosPmApcString),
0x19 => (Action::Ignore, State::SosPmApcString),
0x1C..=0x1F => (Action::Ignore, State::SosPmApcString),
0x20..=0x7F => (Action::Ignore, State::SosPmApcString),
_ => (Action::None, State::Error),
},
}
}