From cbbdde316eea3ee1e6ac5ab75c98797b5a9ad2c7 Mon Sep 17 00:00:00 2001 From: Boaz Yaniv Date: Thu, 17 Oct 2024 15:14:22 +0900 Subject: [PATCH] Split opauqe_*() functions into sos_*(), pm_*(), apc_*(). Split the `opaque_[start|put|end]()` set of functions into 3 different sets of functions for SOS, PM and APC sequences. --- src/lib.rs | 186 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 158 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a82195f..ba7b226 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,7 @@ pub struct Parser { osc_num_params: usize, ignoring: bool, utf8_parser: utf8::Parser, + opaque_sequence_kind: Option, } impl Parser { @@ -385,10 +386,34 @@ impl Parser { // byte value, this branch is unreachable. _ => unreachable!("invalid opaque sequence kind"), }; - performer.opaque_start(kind) + self.opaque_sequence_kind = Some(kind); + match kind { + OpaqueSequenceKind::Sos => performer.sos_start(), + OpaqueSequenceKind::Pm => performer.pm_start(), + OpaqueSequenceKind::Apc => performer.apc_start(), + } + }, + Action::OpaquePut => { + match self.opaque_sequence_kind { + Some(OpaqueSequenceKind::Sos) => performer.sos_put(byte), + Some(OpaqueSequenceKind::Pm) => performer.pm_put(byte), + Some(OpaqueSequenceKind::Apc) => performer.apc_put(byte), + // This action is only triggered inside the OpaqueString state, which requires + // that the opaque_sequence_kind is set to a Some(x) value. + None => unreachable!("opaque sequence kind not set"), + } + }, + Action::OpaqueEnd => { + match self.opaque_sequence_kind { + Some(OpaqueSequenceKind::Sos) => performer.sos_end(), + Some(OpaqueSequenceKind::Pm) => performer.pm_end(), + Some(OpaqueSequenceKind::Apc) => performer.apc_end(), + // This action is only triggered inside the OpaqueString state, which requires + // that the opaque_sequence_kind is set to a Some(x) value. + None => unreachable!("opaque sequence kind not set"), + } + self.opaque_sequence_kind = None; }, - Action::OpaquePut => performer.opaque_put(byte), - Action::OpaqueEnd => performer.opaque_end(), } } } @@ -454,19 +479,41 @@ pub trait Perform { /// subsequent characters were ignored. fn esc_dispatch(&mut self, _intermediates: &[u8], _ignore: bool, _byte: u8) {} - /// The start of an opaque sequence (SOS, PM or APC) has been detected. + /// The start of an SOS sequence has been detected. /// - /// The `kind` parameter indicates the type of sequence that was started. + /// Until the SOS sequence ends (at which point `sos_end` will be called), invalid + /// characters will be ignored while valid characters will be passed on to `sos_put`. + fn sos_start(&mut self) {} + + /// A byte has been received as part of an ongoing SOS sequence. + fn sos_put(&mut self, _byte: u8) {} + + /// We've reached the end of the ongoing SOS sequence. + fn sos_end(&mut self) {} + + /// The start of a PM sequence has been detected. + /// + /// Until the PM sequence ends (at which point `pm_end` will be called), invalid + /// characters will be ignored while valid characters will be passed on to `pm_put`. + fn pm_start(&mut self) {} + + /// A byte has been received as part of an ongoing PM sequence. + fn pm_put(&mut self, _byte: u8) {} + + /// We've reached the end of the ongoing PM sequence. + fn pm_end(&mut self) {} + + /// The start of an APC sequence has been detected. /// - /// Until the opaque sequence ends (at which point `opaque_end` will be called), invalid - /// characters will be ignored while valid characters will be passed on to `opaque_put`. - fn opaque_start(&mut self, _kind: OpaqueSequenceKind) {} + /// Until the APC sequence ends (at which point `apc_end` will be called), invalid + /// characters will be ignored while valid characters will be passed on to `apc_put`. + fn apc_start(&mut self) {} - /// We've reached the end of the ongoing opaque sequence (SOS, PM or APC). - fn opaque_end(&mut self) {} + /// A byte has been received as part of an ongoing APC sequence. + fn apc_put(&mut self, _byte: u8) {} - /// A byte has been received as part of an ongoing opaque sequence. - fn opaque_put(&mut self, _byte: u8) {} + /// We've reached the end of the ongoing APC sequence. + fn apc_end(&mut self) {} } #[cfg(all(test, feature = "no_std"))] @@ -499,9 +546,15 @@ mod tests { DcsHook(Vec>, Vec, bool, char), DcsPut(u8), DcsUnhook, - OpaqueStart(OpaqueSequenceKind), - OpaquePut(u8), - OpaqueEnd, + SosStart, + SosPut(u8), + SosEnd, + PmStart, + PmPut(u8), + PmEnd, + ApcStart, + ApcPut(u8), + ApcEnd, } impl Perform for Dispatcher { @@ -535,16 +588,40 @@ mod tests { self.dispatched.push(Sequence::DcsUnhook); } - fn opaque_start(&mut self, _kind: OpaqueSequenceKind) { - self.dispatched.push(Sequence::OpaqueStart(_kind)); + fn sos_start(&mut self) { + self.dispatched.push(Sequence::SosStart); } - fn opaque_put(&mut self, byte: u8) { - self.dispatched.push(Sequence::OpaquePut(byte)); + fn sos_put(&mut self, byte: u8) { + self.dispatched.push(Sequence::SosPut(byte)); } - fn opaque_end(&mut self) { - self.dispatched.push(Sequence::OpaqueEnd); + fn sos_end(&mut self) { + self.dispatched.push(Sequence::SosEnd); + } + + fn pm_start(&mut self) { + self.dispatched.push(Sequence::PmStart); + } + + fn pm_put(&mut self, byte: u8) { + self.dispatched.push(Sequence::PmPut(byte)); + } + + fn pm_end(&mut self) { + self.dispatched.push(Sequence::PmEnd); + } + + fn apc_start(&mut self) { + self.dispatched.push(Sequence::ApcStart); + } + + fn apc_put(&mut self, byte: u8) { + self.dispatched.push(Sequence::ApcPut(byte)); + } + + fn apc_end(&mut self) { + self.dispatched.push(Sequence::ApcEnd); } } @@ -682,6 +759,56 @@ mod tests { } } + #[test] + fn parse_sos() { + const INPUT: &[u8] = b"\x1bXabc\x1b\\"; + + // Test with ESC \ terminator. + + let mut dispatcher = Dispatcher::default(); + let mut parser = Parser::new(); + + for byte in INPUT { + parser.advance(&mut dispatcher, *byte); + } + assert_eq!(dispatcher.dispatched.len(), 6); + assert_eq!( + dispatcher.dispatched[0..5], + vec![ + Sequence::SosStart, + Sequence::SosPut(b'a'), + Sequence::SosPut(b'b'), + Sequence::SosPut(b'c'), + Sequence::SosEnd, + ] + ) + } + + #[test] + fn parse_pm() { + const INPUT: &[u8] = b"\x1b^abc\x1b\\"; + + // Test with ESC \ terminator. + + let mut dispatcher = Dispatcher::default(); + let mut parser = Parser::new(); + + for byte in INPUT { + parser.advance(&mut dispatcher, *byte); + } + assert_eq!(dispatcher.dispatched.len(), 6); + assert_eq!( + dispatcher.dispatched[0..5], + vec![ + Sequence::PmStart, + Sequence::PmPut(b'a'), + Sequence::PmPut(b'b'), + Sequence::PmPut(b'c'), + Sequence::PmEnd, + ] + ) + } + #[test] fn parse_apc() { const INPUT: &[u8] = b"\x1b_abc\x1b\\"; @@ -695,13 +822,16 @@ mod tests { parser.advance(&mut dispatcher, *byte); } assert_eq!(dispatcher.dispatched.len(), 6); - assert_eq!(dispatcher.dispatched[0..5], vec![ - Sequence::OpaqueStart(OpaqueSequenceKind::Apc), - Sequence::OpaquePut(b'a'), - Sequence::OpaquePut(b'b'), - Sequence::OpaquePut(b'c'), - Sequence::OpaqueEnd, - ]) + assert_eq!( + dispatcher.dispatched[0..5], + vec![ + Sequence::ApcStart, + Sequence::ApcPut(b'a'), + Sequence::ApcPut(b'b'), + Sequence::ApcPut(b'c'), + Sequence::ApcEnd, + ] + ) } #[test]