aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs540
1 files changed, 392 insertions, 148 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 1f229a3..55fa676 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -35,13 +35,10 @@ use core::str;
#[cfg(feature = "no_std")]
use arrayvec::ArrayVec;
-mod definitions;
mod params;
-mod table;
#[cfg(feature = "ansi")]
pub mod ansi;
-use definitions::{unpack, Action, State};
pub use params::{Params, ParamsIter};
const MAX_INTERMEDIATES: usize = 2;
@@ -113,7 +110,7 @@ impl<const OSC_RAW_BUF_SIZE: usize> Parser<OSC_RAW_BUF_SIZE> {
let mut i = 0;
// Handle partial codepoints from previous calls to `advance`.
- if self.partial_utf8_len > 0 {
+ if self.partial_utf8_len != 0 {
i += self.advance_partial_utf8(performer, bytes);
}
@@ -121,12 +118,9 @@ impl<const OSC_RAW_BUF_SIZE: usize> Parser<OSC_RAW_BUF_SIZE> {
match self.state {
State::Ground => i += self.advance_ground(performer, &bytes[i..]),
_ => {
+ // Inlining it results in worse codegen.
let byte = bytes[i];
- let change = table::STATE_CHANGES[self.state as usize][byte as usize];
- let (state, action) = unpack(change);
-
- self.perform_state_change(performer, state, action, byte);
-
+ self.change_state(performer, byte);
i += 1;
},
}
@@ -159,12 +153,9 @@ impl<const OSC_RAW_BUF_SIZE: usize> Parser<OSC_RAW_BUF_SIZE> {
match self.state {
State::Ground => i += self.advance_ground(performer, &bytes[i..]),
_ => {
+ // Inlining it results in worse codegen.
let byte = bytes[i];
- let change = table::STATE_CHANGES[self.state as usize][byte as usize];
- let (state, action) = unpack(change);
-
- self.perform_state_change(performer, state, action, byte);
-
+ self.change_state(performer, byte);
i += 1;
},
}
@@ -173,164 +164,398 @@ impl<const OSC_RAW_BUF_SIZE: usize> Parser<OSC_RAW_BUF_SIZE> {
i
}
- #[inline]
- fn perform_state_change<P>(&mut self, performer: &mut P, state: State, action: Action, byte: u8)
- where
- P: Perform,
- {
- if state == State::Anywhere {
- self.perform_action(performer, action, byte);
- return;
+ #[inline(always)]
+ fn change_state<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match self.state {
+ State::CsiEntry => self.advance_csi_entry(performer, byte),
+ State::CsiIgnore => self.advance_csi_ignore(performer, byte),
+ State::CsiIntermediate => self.advance_csi_intermediate(performer, byte),
+ State::CsiParam => self.advance_csi_param(performer, byte),
+ State::DcsEntry => self.advance_dcs_entry(performer, byte),
+ State::DcsIgnore => self.anywhere(performer, byte),
+ State::DcsIntermediate => self.advance_dcs_intermediate(performer, byte),
+ State::DcsParam => self.advance_dcs_param(performer, byte),
+ State::DcsPassthrough => self.advance_dcs_passthrough(performer, byte),
+ State::Escape => self.advance_esc(performer, byte),
+ State::EscapeIntermediate => self.advance_esc_intermediate(performer, byte),
+ State::OscString => self.advance_osc_string(performer, byte),
+ State::SosPmApcString => self.anywhere(performer, byte),
+ State::Ground => unreachable!(),
}
+ }
- match self.state {
- State::DcsPassthrough => performer.unhook(),
- State::OscString => {
- let param_idx = self.osc_num_params;
- let idx = self.osc_raw.len();
-
- match param_idx {
- // Finish last parameter if not already maxed
- MAX_OSC_PARAMS => (),
-
- // First param is special - 0 to current byte index
- 0 => {
- self.osc_params[param_idx] = (0, idx);
- self.osc_num_params += 1;
- },
+ #[inline(always)]
+ fn advance_csi_entry<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x2F => {
+ self.action_collect(byte);
+ self.state = State::CsiIntermediate
+ },
+ 0x30..=0x39 => {
+ self.action_paramnext(byte);
+ self.state = State::CsiParam
+ },
+ 0x3A => {
+ self.action_subparam();
+ self.state = State::CsiParam
+ },
+ 0x3B => {
+ self.action_param();
+ self.state = State::CsiParam
+ },
+ 0x3C..=0x3F => {
+ self.action_collect(byte);
+ self.state = State::CsiParam
+ },
+ 0x40..=0x7E => self.action_csi_dispatch(performer, byte),
+ _ => self.anywhere(performer, byte),
+ }
+ }
- // All other params depend on previous indexing
- _ => {
- let prev = self.osc_params[param_idx - 1];
- let begin = prev.1;
- self.osc_params[param_idx] = (begin, idx);
- self.osc_num_params += 1;
- },
- }
- self.osc_dispatch(performer, byte);
+ #[inline(always)]
+ fn advance_csi_ignore<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x3F => (),
+ 0x40..=0x7E => self.state = State::Ground,
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
+ }
+ }
+
+ #[inline(always)]
+ fn advance_csi_intermediate<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x2F => self.action_collect(byte),
+ 0x30..=0x3F => self.state = State::CsiIgnore,
+ 0x40..=0x7E => self.action_csi_dispatch(performer, byte),
+ _ => self.anywhere(performer, byte),
+ }
+ }
+
+ #[inline(always)]
+ fn advance_csi_param<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x2F => {
+ self.action_collect(byte);
+ self.state = State::CsiIntermediate
},
- _ => (),
+ 0x30..=0x39 => self.action_paramnext(byte),
+ 0x3A => self.action_subparam(),
+ 0x3B => self.action_param(),
+ 0x3C..=0x3F => self.state = State::CsiIgnore,
+ 0x40..=0x7E => self.action_csi_dispatch(performer, byte),
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
}
+ }
- if action == Action::None {
- match state {
- State::CsiEntry | State::DcsEntry | State::Escape => self.reset_params(),
- State::DcsPassthrough => {
- if self.params.is_full() {
- self.ignoring = true;
- } else {
- self.params.push(self.param);
- }
+ #[inline(always)]
+ fn advance_dcs_entry<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => (),
+ 0x20..=0x2F => {
+ self.action_collect(byte);
+ self.state = State::DcsIntermediate
+ },
+ 0x30..=0x39 => {
+ self.action_paramnext(byte);
+ self.state = State::DcsParam
+ },
+ 0x3A => {
+ self.action_subparam();
+ self.state = State::DcsParam
+ },
+ 0x3B => {
+ self.action_param();
+ self.state = State::DcsParam
+ },
+ 0x3C..=0x3F => {
+ self.action_collect(byte);
+ self.state = State::DcsParam
+ },
+ 0x40..=0x7E => self.action_hook(performer, byte),
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
+ }
+ }
- performer.hook(
- self.params(),
- self.intermediates(),
- self.ignoring,
- byte as char,
- );
- },
- State::OscString => {
- self.osc_raw.clear();
- self.osc_num_params = 0;
- },
- _ => (),
- }
- } else {
- self.perform_action(performer, action, byte);
+ #[inline(always)]
+ fn advance_dcs_intermediate<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => (),
+ 0x20..=0x2F => self.action_collect(byte),
+ 0x30..=0x3F => self.state = State::DcsIgnore,
+ 0x40..=0x7E => self.action_hook(performer, byte),
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
}
+ }
- self.state = state;
+ #[inline(always)]
+ fn advance_dcs_param<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => (),
+ 0x20..=0x2F => {
+ self.action_collect(byte);
+ self.state = State::DcsIntermediate
+ },
+ 0x30..=0x39 => self.action_paramnext(byte),
+ 0x3A => self.action_subparam(),
+ 0x3B => self.action_param(),
+ 0x3C..=0x3F => self.state = State::DcsIgnore,
+ 0x40..=0x7E => self.action_hook(performer, byte),
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
+ }
}
- #[inline]
- fn perform_action<P: Perform>(&mut self, performer: &mut P, action: Action, byte: u8) {
- match action {
- Action::Execute => performer.execute(byte),
- Action::Put => performer.put(byte),
- Action::OscPut => {
+ #[inline(always)]
+ fn advance_dcs_passthrough<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x7E => performer.put(byte),
+ 0x18 | 0x1A => {
+ performer.unhook();
+ performer.execute(byte);
+ self.state = State::Ground
+ },
+ 0x1B => {
+ performer.unhook();
+ self.reset_params();
+ self.state = State::Escape
+ },
+ 0x7F => (),
+ 0x9C => {
+ performer.unhook();
+ self.state = State::Ground
+ },
+ _ => (),
+ }
+ }
+
+ #[inline(always)]
+ fn advance_esc<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x2F => {
+ self.action_collect(byte);
+ self.state = State::EscapeIntermediate
+ },
+ 0x30..=0x4F => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ 0x50 => {
+ self.reset_params();
+ self.state = State::DcsEntry
+ },
+ 0x51..=0x57 => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ 0x58 => self.state = State::SosPmApcString,
+ 0x59..=0x5A => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ 0x5B => {
+ self.reset_params();
+ self.state = State::CsiEntry
+ },
+ 0x5C => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ 0x5D => {
+ self.osc_raw.clear();
+ self.osc_num_params = 0;
+ self.state = State::OscString
+ },
+ 0x5E..=0x5F => self.state = State::SosPmApcString,
+ 0x60..=0x7E => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ // Anywhere.
+ 0x18 | 0x1A => {
+ performer.execute(byte);
+ self.state = State::Ground
+ },
+ 0x1B => (),
+ _ => (),
+ }
+ }
+
+ #[inline(always)]
+ fn advance_esc_intermediate<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x17 | 0x19 | 0x1C..=0x1F => performer.execute(byte),
+ 0x20..=0x2F => self.action_collect(byte),
+ 0x30..=0x7E => {
+ performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ self.state = State::Ground
+ },
+ 0x7F => (),
+ _ => self.anywhere(performer, byte),
+ }
+ }
+
+ #[inline(always)]
+ fn advance_osc_string<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x00..=0x06 | 0x08..=0x17 | 0x19 | 0x1C..=0x1F => (),
+ 0x07 => {
+ self.osc_end(performer, byte);
+ self.state = State::Ground
+ },
+ 0x18 | 0x1A => {
+ self.osc_end(performer, byte);
+ performer.execute(byte);
+ self.state = State::Ground
+ },
+ 0x1B => {
+ self.osc_end(performer, byte);
+ self.reset_params();
+ self.state = State::Escape
+ },
+ 0x3B => {
#[cfg(feature = "no_std")]
{
if self.osc_raw.is_full() {
return;
}
}
-
- let idx = self.osc_raw.len();
-
- // Param separator
- if byte == b';' {
- let param_idx = self.osc_num_params;
- match param_idx {
- // Only process up to MAX_OSC_PARAMS
- MAX_OSC_PARAMS => return,
-
- // First param is special - 0 to current byte index
- 0 => {
- self.osc_params[param_idx] = (0, idx);
- },
-
- // All other params depend on previous indexing
- _ => {
- let prev = self.osc_params[param_idx - 1];
- let begin = prev.1;
- self.osc_params[param_idx] = (begin, idx);
- },
- }
-
- self.osc_num_params += 1;
- } else {
- self.osc_raw.push(byte);
- }
+ self.action_osc_put_param()
},
- Action::CsiDispatch => {
- if self.params.is_full() {
- self.ignoring = true;
- } else {
- self.params.push(self.param);
- }
+ _ => self.action_osc_put(byte),
+ }
+ }
- performer.csi_dispatch(
- self.params(),
- self.intermediates(),
- self.ignoring,
- byte as char,
- );
- },
- Action::EscDispatch => {
- performer.esc_dispatch(self.intermediates(), self.ignoring, byte);
+ #[inline(always)]
+ fn anywhere<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ match byte {
+ 0x18 | 0x1A => {
+ performer.execute(byte);
+ self.state = State::Ground
},
- Action::Collect => {
- if self.intermediate_idx == MAX_INTERMEDIATES {
- self.ignoring = true;
- } else {
- self.intermediates[self.intermediate_idx] = byte;
- self.intermediate_idx += 1;
- }
+ 0x1B => {
+ self.reset_params();
+ self.state = State::Escape
},
- Action::Param => {
- if self.params.is_full() {
- self.ignoring = true;
- return;
- }
+ _ => (),
+ }
+ }
- match byte {
- b';' => {
- self.params.push(self.param);
- self.param = 0;
- },
- b':' => {
- self.params.extend(self.param);
- self.param = 0;
- },
- _ => {
- // Continue collecting bytes into param
- self.param = self.param.saturating_mul(10);
- self.param = self.param.saturating_add((byte - b'0') as u16);
- },
- }
+ #[inline]
+ fn action_csi_dispatch<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ if self.params.is_full() {
+ self.ignoring = true;
+ } else {
+ self.params.push(self.param);
+ }
+ performer.csi_dispatch(self.params(), self.intermediates(), self.ignoring, byte as char);
+
+ self.state = State::Ground
+ }
+
+ #[inline]
+ fn action_hook<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ if self.params.is_full() {
+ self.ignoring = true;
+ } else {
+ self.params.push(self.param);
+ }
+ performer.hook(self.params(), self.intermediates(), self.ignoring, byte as char);
+ self.state = State::DcsPassthrough;
+ }
+
+ #[inline]
+ fn action_collect(&mut self, byte: u8) {
+ if self.intermediate_idx == MAX_INTERMEDIATES {
+ self.ignoring = true;
+ } else {
+ self.intermediates[self.intermediate_idx] = byte;
+ self.intermediate_idx += 1;
+ }
+ }
+
+ /// Advance to the next subparameter.
+ #[inline]
+ fn action_subparam(&mut self) {
+ if self.params.is_full() {
+ self.ignoring = true;
+ } else {
+ self.params.extend(self.param);
+ self.param = 0;
+ }
+ }
+
+ /// Advance to the next parameter.
+ #[inline]
+ fn action_param(&mut self) {
+ if self.params.is_full() {
+ self.ignoring = true;
+ } else {
+ self.params.push(self.param);
+ self.param = 0;
+ }
+ }
+
+ /// Advance inside the parameter without terminating it.
+ #[inline]
+ fn action_paramnext(&mut self, byte: u8) {
+ if self.params.is_full() {
+ self.ignoring = true;
+ } else {
+ // Continue collecting bytes into param.
+ self.param = self.param.saturating_mul(10);
+ self.param = self.param.saturating_add((byte - b'0') as u16);
+ }
+ }
+
+ /// Add OSC param separator.
+ #[inline]
+ fn action_osc_put_param(&mut self) {
+ let idx = self.osc_raw.len();
+
+ let param_idx = self.osc_num_params;
+ match param_idx {
+ // First param is special - 0 to current byte index.
+ 0 => self.osc_params[param_idx] = (0, idx),
+
+ // Only process up to MAX_OSC_PARAMS.
+ MAX_OSC_PARAMS => return,
+
+ // All other params depend on previous indexing.
+ _ => {
+ let prev = self.osc_params[param_idx - 1];
+ let begin = prev.1;
+ self.osc_params[param_idx] = (begin, idx);
},
- _ => (),
}
+
+ self.osc_num_params += 1;
+ }
+
+ #[inline(always)]
+ fn action_osc_put(&mut self, byte: u8) {
+ #[cfg(feature = "no_std")]
+ {
+ if self.osc_raw.is_full() {
+ return;
+ }
+ }
+ self.osc_raw.push(byte);
+ }
+
+ fn osc_end<P: Perform>(&mut self, performer: &mut P, byte: u8) {
+ self.action_osc_put_param();
+ self.osc_dispatch(performer, byte);
+ self.osc_raw.clear();
+ self.osc_num_params = 0;
}
/// Reset escape sequence parameters and intermediates.
@@ -504,6 +729,25 @@ impl<const OSC_RAW_BUF_SIZE: usize> Parser<OSC_RAW_BUF_SIZE> {
}
}
+#[derive(PartialEq, Eq, Debug, Default, Copy, Clone)]
+enum State {
+ CsiEntry,
+ CsiIgnore,
+ CsiIntermediate,
+ CsiParam,
+ DcsEntry,
+ DcsIgnore,
+ DcsIntermediate,
+ DcsParam,
+ DcsPassthrough,
+ Escape,
+ EscapeIntermediate,
+ OscString,
+ SosPmApcString,
+ #[default]
+ Ground,
+}
+
/// Performs actions requested by the Parser
///
/// Actions in this case mean, for example, handling a CSI escape sequence