vt_push_parser/
event.rs

1//! Event types.
2use std::iter::Map;
3
4use smallvec::SmallVec;
5
6use crate::AsciiControl;
7
8/// Helper function to format UTF-8 chunks with ASCII control character handling
9fn fmt_utf8_bytes_with_ascii_control(
10    f: &mut std::fmt::Formatter<'_>,
11    bytes: &[u8],
12) -> std::fmt::Result {
13    for chunk in bytes.utf8_chunks() {
14        for c in chunk.valid().chars() {
15            if let Ok(c) = AsciiControl::try_from(c) {
16                write!(f, "{c}")?;
17            } else {
18                write!(f, "{c}")?;
19            }
20        }
21        if !chunk.invalid().is_empty() {
22            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
23        }
24    }
25    Ok(())
26}
27
28/// Helper function to format UTF-8 chunks for parameters (simple formatting)
29fn fmt_utf8_bytes_simple(f: &mut std::fmt::Formatter<'_>, bytes: &[u8]) -> std::fmt::Result {
30    for chunk in bytes.utf8_chunks() {
31        write!(f, "{}", chunk.valid())?;
32        if !chunk.invalid().is_empty() {
33            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
34        }
35    }
36    Ok(())
37}
38
39#[cfg_attr(feature = "serde", derive(serde::Serialize))]
40#[derive(Default, Clone, Copy, PartialEq, Eq)]
41pub struct VTIntermediate {
42    pub(crate) data: [u8; 2],
43}
44
45impl VTIntermediate {
46    pub const fn empty() -> Self {
47        Self { data: [0, 0] }
48    }
49
50    pub const fn one(c: u8) -> Self {
51        assert!(c >= 0x20 && c <= 0x2F);
52        Self { data: [c, 0] }
53    }
54
55    pub const fn two(c1: u8, c2: u8) -> Self {
56        assert!(c1 >= 0x20 && c1 <= 0x2F);
57        assert!(c2 >= 0x20 && c2 <= 0x2F);
58        Self { data: [c1, c2] }
59    }
60
61    pub fn has(&self, c: u8) -> bool {
62        self.data[0] == c || self.data[1] == c
63    }
64
65    pub fn clear(&mut self) {
66        self.data[0] = 0;
67        self.data[1] = 0;
68    }
69
70    pub fn is_empty(&self) -> bool {
71        self.data[0] == 0 && self.data[1] == 0
72    }
73
74    pub fn len(&self) -> usize {
75        self.data.iter().filter(|&&c| c != 0).count()
76    }
77
78    pub fn first(&self) -> Option<u8> {
79        if self.data[0] != 0 {
80            Some(self.data[0])
81        } else {
82            None
83        }
84    }
85
86    pub fn second(&self) -> Option<u8> {
87        if self.data[1] != 0 {
88            Some(self.data[1])
89        } else {
90            None
91        }
92    }
93
94    #[must_use]
95    pub fn push(&mut self, c: u8) -> bool {
96        if !(0x20..=0x2F).contains(&c) {
97            return false;
98        }
99
100        // Invalid duplicate intermediate
101        if self.data[0] == c {
102            return false;
103        }
104
105        if self.data[0] == 0 {
106            self.data[0] = c;
107            true
108        } else if self.data[1] == 0 {
109            self.data[1] = c;
110            true
111        } else {
112            false
113        }
114    }
115
116    pub const fn const_eq(&self, other: &Self) -> bool {
117        self.data[0] == other.data[0] && self.data[1] == other.data[1]
118    }
119
120    pub fn byte_len(&self) -> usize {
121        self.data.iter().filter(|&&c| c != 0).count()
122    }
123}
124
125impl std::fmt::Debug for VTIntermediate {
126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127        // Inefficient
128        write!(f, "'")?;
129        for c in self.data.iter() {
130            if *c == 0 {
131                break;
132            }
133            write!(f, "{}", *c as char)?;
134        }
135        write!(f, "'")?;
136        Ok(())
137    }
138}
139
140pub(crate) type Param = SmallVec<[u8; 32]>;
141pub(crate) type Params = SmallVec<[Param; 8]>;
142
143static EMPTY_PARAMS: Params = Params::new_const();
144
145#[cfg_attr(feature = "serde", derive(serde::Serialize))]
146#[derive(Debug, Copy, Clone, PartialEq, Eq)]
147#[repr(transparent)]
148pub struct ParamBuf<'a> {
149    pub(crate) params: &'a Params,
150}
151
152impl<'a> IntoIterator for ParamBuf<'a> {
153    type Item = &'a [u8];
154    type IntoIter = Map<std::slice::Iter<'a, Param>, fn(&Param) -> &[u8]>;
155    fn into_iter(self) -> Self::IntoIter {
156        self.params.iter().map(|p| p.as_slice())
157    }
158}
159
160impl<'a> IntoIterator for &ParamBuf<'a> {
161    type Item = &'a [u8];
162    type IntoIter = Map<std::slice::Iter<'a, Param>, fn(&Param) -> &[u8]>;
163    fn into_iter(self) -> Self::IntoIter {
164        self.params.iter().map(|p| p.as_slice())
165    }
166}
167
168impl<'a> ParamBuf<'a> {
169    pub const fn empty() -> Self {
170        ParamBuf {
171            params: &EMPTY_PARAMS,
172        }
173    }
174
175    pub fn len(&self) -> usize {
176        self.params.len()
177    }
178
179    pub fn is_empty(&self) -> bool {
180        self.params.is_empty()
181    }
182
183    pub fn get(&self, index: usize) -> Option<&[u8]> {
184        self.params.get(index).map(|p| p.as_slice())
185    }
186
187    pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
188        self.params.get(index).and_then(|p| {
189            std::str::from_utf8(p.as_slice())
190                .ok()
191                .and_then(|s| s.parse::<T>().ok())
192        })
193    }
194
195    pub fn to_owned(&self) -> ParamBufOwned {
196        ParamBufOwned {
197            params: self.params.iter().cloned().collect(),
198        }
199    }
200
201    pub fn byte_len(&self) -> usize {
202        self.params.iter().map(|p| p.len()).sum::<usize>() + self.params.len().saturating_sub(1)
203    }
204
205    pub fn numeric(&self) -> NumericParamBuf<'a> {
206        NumericParamBuf {
207            params: self.params,
208        }
209    }
210}
211
212/// A view into a [`Param`] that contains only numeric parameters.
213#[derive(Debug, Copy, Clone, Default)]
214pub struct NumericParam<'a> {
215    pub(crate) param: &'a [u8],
216}
217
218impl<'a> IntoIterator for NumericParam<'a> {
219    type Item = Option<u16>;
220    type IntoIter = Map<std::slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> Option<u16>>;
221    fn into_iter(self) -> Self::IntoIter {
222        let fn1: fn(&u8) -> bool = |c: &u8| *c == b':';
223        self.param.split(fn1).map(|p| {
224            if p.is_empty() {
225                None
226            } else {
227                std::str::from_utf8(p)
228                    .ok()
229                    .and_then(|s| s.parse::<u16>().ok())
230            }
231        })
232    }
233}
234
235/// A view into a [`ParamBuf`] that contains only numeric parameters.
236///
237/// Each parameter may contain zero or more numeric values, separated by colons.
238/// Empty parameters are interpreted as `None`.
239#[derive(Debug, Copy, Clone)]
240pub struct NumericParamBuf<'a> {
241    pub(crate) params: &'a Params,
242}
243
244impl<'a> IntoIterator for NumericParamBuf<'a> {
245    type Item = NumericParam<'a>;
246    type IntoIter = Map<std::slice::Iter<'a, Param>, fn(&'a Param) -> NumericParam<'a>>;
247    fn into_iter(self) -> Self::IntoIter {
248        self.params.iter().map(|p| NumericParam {
249            param: p.as_slice(),
250        })
251    }
252}
253
254impl<'a> NumericParamBuf<'a> {
255    pub const fn empty() -> Self {
256        NumericParamBuf {
257            params: &EMPTY_PARAMS,
258        }
259    }
260}
261
262/// A union of all possible events that can be emitted by the parser, with
263/// borrowed data.
264#[cfg_attr(feature = "serde", derive(serde::Serialize))]
265#[derive(Clone, PartialEq, Eq)]
266pub enum VTEvent<'a> {
267    // Plain printable text from GROUND (coalesced)
268    Raw(&'a [u8]),
269
270    // C0 control (EXECUTE)
271    C0(u8),
272
273    // ESC final (with intermediates)
274    Esc(Esc),
275
276    // Invalid escape sequence
277    EscInvalid(EscInvalid),
278
279    // SS2
280    Ss2(SS2),
281
282    // SS3
283    Ss3(SS3),
284
285    // CSI short escape
286    Csi(CSI<'a>),
287
288    // DCS stream
289    DcsStart(DCS<'a>),
290    DcsData(&'a [u8]),
291    DcsEnd(&'a [u8]),
292    DcsCancel,
293
294    // OSC stream
295    OscStart,
296    OscData(&'a [u8]),
297    OscEnd {
298        data: &'a [u8],
299        /// Whether the BEL was used to end the OSC stream.
300        used_bel: bool,
301    },
302    OscCancel,
303}
304
305impl<'a> std::fmt::Debug for VTEvent<'a> {
306    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
307        use VTEvent::*;
308        match self {
309            Raw(s) => {
310                write!(f, "Raw('")?;
311                fmt_utf8_bytes_with_ascii_control(f, s)?;
312                write!(f, "')")?;
313                Ok(())
314            }
315            EscInvalid(esc_invalid) => esc_invalid.fmt(f),
316            C0(b) => write!(f, "C0({b:02x})"),
317            Esc(esc) => esc.fmt(f),
318            Ss2(ss2) => ss2.fmt(f),
319            Ss3(ss3) => ss3.fmt(f),
320            Csi(csi) => csi.fmt(f),
321            DcsStart(dcs_start) => dcs_start.fmt(f),
322            DcsData(s) | DcsEnd(s) => {
323                if matches!(self, DcsEnd(..)) {
324                    write!(f, "DcsEnd('")?;
325                } else {
326                    write!(f, "DcsData('")?;
327                }
328                fmt_utf8_bytes_with_ascii_control(f, s)?;
329                write!(f, "')")?;
330                Ok(())
331            }
332            DcsCancel => write!(f, "DcsCancel"),
333            OscStart => write!(f, "OscStart"),
334            OscData(s) | OscEnd { data: s, .. } => {
335                if matches!(self, OscEnd { .. }) {
336                    write!(f, "OscEnd('")?;
337                } else {
338                    write!(f, "OscData('")?;
339                }
340                fmt_utf8_bytes_with_ascii_control(f, s)?;
341                write!(f, "')")?;
342                Ok(())
343            }
344            OscCancel => write!(f, "OscCancel"),
345        }
346    }
347}
348
349impl<'a> VTEvent<'a> {
350    pub fn csi(&self) -> Option<CSI> {
351        match self {
352            VTEvent::Csi(csi) => Some(CSI {
353                private: csi.private,
354                params: csi.params,
355                intermediates: csi.intermediates,
356                final_byte: csi.final_byte,
357            }),
358            _ => None,
359        }
360    }
361
362    pub fn byte_len(&self) -> usize {
363        use VTEvent::*;
364
365        match self {
366            Raw(s) => s.len(),
367            C0(_) => 1,
368            Esc(esc) => esc.intermediates.len() + 2 + esc.private.is_some() as usize,
369            EscInvalid(esc_invalid) => {
370                use self::EscInvalid::*;
371                match esc_invalid {
372                    One(..) => 2,
373                    Two(..) => 3,
374                    Three(..) => 4,
375                    Four(..) => 5,
376                }
377            }
378            Ss2(_) => 3,
379            Ss3(_) => 3,
380            Csi(csi) => {
381                csi.private.is_some() as usize
382                    + csi.params.byte_len()
383                    + csi.intermediates.byte_len()
384                    + 3
385            }
386            DcsStart(dcs_start) => {
387                dcs_start.private.is_some() as usize
388                    + dcs_start.params.byte_len()
389                    + dcs_start.intermediates.byte_len()
390                    + 3
391            }
392            DcsData(s) => s.len(),
393            DcsEnd(s) => s.len() + 2,
394            DcsCancel => 1,
395            OscStart => 2,
396            OscData(s) => s.len(),
397            OscEnd { data, used_bel } => {
398                if *used_bel {
399                    data.len() + 1
400                } else {
401                    data.len() + 2
402                }
403            }
404            OscCancel => 1,
405        }
406    }
407
408    /// Encode the event into the provided buffer, returning the number of bytes
409    /// required for the escape sequence in either `Ok(n)` or `Err(n)`.
410    ///
411    /// Note that some events may have multiple possible encodings, so this method
412    /// may decide to choose whichever is more efficient.
413    pub fn encode(&self, mut buf: &mut [u8]) -> Result<usize, usize> {
414        use crate::{BEL, CAN, CSI, DCS, ESC, OSC, SS2, SS3, ST_FINAL};
415        use VTEvent::*;
416
417        let len = self.byte_len();
418
419        if len > buf.len() {
420            return Err(len);
421        }
422
423        match self {
424            Raw(s) | OscData(s) | DcsData(s) => {
425                buf[..s.len()].copy_from_slice(s);
426            }
427            EscInvalid(esc_invalid) => {
428                use self::EscInvalid::*;
429                buf[0] = ESC;
430                match esc_invalid {
431                    One(b) => buf[1] = *b,
432                    Two(b1, b2) => {
433                        buf[1] = *b1;
434                        buf[2] = *b2;
435                    }
436                    Three(b1, b2, b3) => {
437                        buf[1] = *b1;
438                        buf[2] = *b2;
439                        buf[3] = *b3;
440                    }
441                    Four(b1, b2, b3, b4) => {
442                        buf[1] = *b1;
443                        buf[2] = *b2;
444                        buf[3] = *b3;
445                        buf[4] = *b4;
446                    }
447                }
448            }
449            OscCancel | DcsCancel => {
450                buf[0] = CAN;
451            }
452            C0(b) => {
453                buf[0] = *b;
454            }
455            Ss2(ss2) => {
456                buf[0] = ESC;
457                buf[1] = SS2;
458                buf[2] = ss2.char;
459            }
460            Ss3(ss3) => {
461                buf[0] = ESC;
462                buf[1] = SS3;
463                buf[2] = ss3.char;
464            }
465            Esc(esc) => {
466                buf[0] = ESC;
467                if let Some(p) = esc.private {
468                    buf[1] = p;
469                    buf = &mut buf[1..];
470                }
471                buf[1..esc.intermediates.len() + 1]
472                    .copy_from_slice(&esc.intermediates.data[..esc.intermediates.len()]);
473                buf[esc.intermediates.len() + 1] = esc.final_byte;
474            }
475            Csi(csi) => {
476                buf[0] = ESC;
477                buf[1] = CSI;
478                buf = &mut buf[2..];
479                if let Some(p) = csi.private {
480                    buf[0] = p;
481                    buf = &mut buf[1..];
482                }
483                let mut params = csi.params.into_iter();
484                if let Some(param) = params.next() {
485                    buf[..param.len()].copy_from_slice(param);
486                    buf = &mut buf[param.len()..];
487                    for param in params {
488                        buf[0] = b';';
489                        buf = &mut buf[1..];
490                        buf[..param.len()].copy_from_slice(param);
491                        buf = &mut buf[param.len()..];
492                    }
493                }
494                buf[..csi.intermediates.len()]
495                    .copy_from_slice(&csi.intermediates.data[..csi.intermediates.len()]);
496                buf[csi.intermediates.len()] = csi.final_byte;
497            }
498            DcsStart(dcs_start) => {
499                buf[0] = ESC;
500                buf[1] = DCS;
501                buf = &mut buf[2..];
502                if let Some(p) = dcs_start.private {
503                    buf[0] = p;
504                    buf = &mut buf[1..];
505                }
506                let mut params = dcs_start.params.into_iter();
507                if let Some(param) = params.next() {
508                    buf[..param.len()].copy_from_slice(param);
509                    buf = &mut buf[param.len()..];
510                    for param in params {
511                        buf[0] = b';';
512                        buf = &mut buf[1..];
513                        buf[..param.len()].copy_from_slice(param);
514                        buf = &mut buf[param.len()..];
515                    }
516                }
517                buf[..dcs_start.intermediates.len()].copy_from_slice(
518                    &dcs_start.intermediates.data[..dcs_start.intermediates.len()],
519                );
520                buf[dcs_start.intermediates.len()] = dcs_start.final_byte;
521            }
522            DcsEnd(data) => {
523                buf[..data.len()].copy_from_slice(data);
524                buf = &mut buf[data.len()..];
525                buf[0] = ESC;
526                buf[1] = ST_FINAL;
527            }
528            OscStart => {
529                buf[0] = ESC;
530                buf[1] = OSC;
531            }
532            OscEnd { data, used_bel } => {
533                buf[..data.len()].copy_from_slice(data);
534                buf = &mut buf[data.len()..];
535                if *used_bel {
536                    buf[0] = BEL;
537                } else {
538                    buf[0] = ESC;
539                    buf[1] = ST_FINAL
540                }
541            }
542        }
543
544        Ok(len)
545    }
546
547    pub fn to_owned(&self) -> VTOwnedEvent {
548        use VTEvent::*;
549        match self {
550            Raw(s) => VTOwnedEvent::Raw(s.to_vec()),
551            C0(b) => VTOwnedEvent::C0(*b),
552            Esc(esc) => VTOwnedEvent::Esc(*esc),
553            EscInvalid(esc_invalid) => VTOwnedEvent::EscInvalid(*esc_invalid),
554            Ss2(ss2) => VTOwnedEvent::Ss2(*ss2),
555            Ss3(ss3) => VTOwnedEvent::Ss3(*ss3),
556            Csi(csi) => VTOwnedEvent::Csi(CSIOwned {
557                private: csi.private,
558                params: csi.params.to_owned(),
559                intermediates: csi.intermediates,
560                final_byte: csi.final_byte,
561            }),
562            DcsStart(dcs_start) => VTOwnedEvent::DcsStart(DCSOwned {
563                private: dcs_start.private,
564                params: dcs_start.params.to_owned(),
565                intermediates: dcs_start.intermediates,
566                final_byte: dcs_start.final_byte,
567            }),
568            DcsData(s) => VTOwnedEvent::DcsData(s.to_vec()),
569            DcsEnd(s) => VTOwnedEvent::DcsEnd(s.to_vec()),
570            DcsCancel => VTOwnedEvent::DcsCancel,
571            OscStart => VTOwnedEvent::OscStart,
572            OscData(s) => VTOwnedEvent::OscData(s.to_vec()),
573            OscEnd { data, used_bel } => VTOwnedEvent::OscEnd {
574                data: data.to_vec(),
575                used_bel: *used_bel,
576            },
577            OscCancel => VTOwnedEvent::OscCancel,
578        }
579    }
580}
581
582#[cfg_attr(feature = "serde", derive(serde::Serialize))]
583#[derive(Clone, PartialEq, Eq, Debug, Default)]
584pub struct ParamBufOwned {
585    pub(crate) params: Params,
586}
587
588impl IntoIterator for ParamBufOwned {
589    type Item = Param;
590    type IntoIter = <Params as IntoIterator>::IntoIter;
591    fn into_iter(self) -> Self::IntoIter {
592        self.params.into_iter()
593    }
594}
595
596impl<'b> IntoIterator for &'b ParamBufOwned {
597    type Item = &'b [u8];
598    type IntoIter = Map<std::slice::Iter<'b, Param>, fn(&Param) -> &[u8]>;
599    fn into_iter(self) -> Self::IntoIter {
600        self.params.iter().map(|p| p.as_slice())
601    }
602}
603
604impl ParamBufOwned {
605    /// Create an empty `ParamBufOwned`.
606    pub const fn empty() -> Self {
607        Self {
608            params: SmallVec::new_const(),
609        }
610    }
611
612    /// Create a `ParamBufOwned` from a slice of slices.
613    pub fn new(params: &[&[u8]]) -> Self {
614        Self {
615            params: params.iter().map(|p| Param::from(*p)).collect(),
616        }
617    }
618
619    pub fn len(&self) -> usize {
620        self.params.len()
621    }
622
623    pub fn is_empty(&self) -> bool {
624        self.params.is_empty()
625    }
626
627    pub fn get(&self, index: usize) -> Option<&[u8]> {
628        self.params.get(index).map(|p| p.as_slice())
629    }
630
631    pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
632        self.params.get(index).and_then(|p| {
633            std::str::from_utf8(p.as_slice())
634                .ok()
635                .and_then(|s| s.parse::<T>().ok())
636        })
637    }
638
639    pub fn borrow(&self) -> ParamBuf<'_> {
640        ParamBuf {
641            params: &self.params,
642        }
643    }
644
645    pub fn numeric(&self) -> NumericParamBuf<'_> {
646        NumericParamBuf {
647            params: &self.params,
648        }
649    }
650}
651
652/// A union of all possible events that can be emitted by the parser, with owned
653/// data.
654#[cfg_attr(feature = "serde", derive(serde::Serialize))]
655#[derive(Clone, PartialEq, Eq)]
656pub enum VTOwnedEvent {
657    Raw(Vec<u8>),
658    C0(u8),
659    Esc(Esc),
660    EscInvalid(EscInvalid),
661    Ss2(SS2),
662    Ss3(SS3),
663    Csi(CSIOwned),
664    DcsStart(DCSOwned),
665    DcsData(Vec<u8>),
666    DcsEnd(Vec<u8>),
667    DcsCancel,
668    OscStart,
669    OscData(Vec<u8>),
670    OscEnd { data: Vec<u8>, used_bel: bool },
671    OscCancel,
672}
673
674impl std::fmt::Debug for VTOwnedEvent {
675    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
676        self.borrow().fmt(f)
677    }
678}
679
680impl VTOwnedEvent {
681    pub fn borrow(&self) -> VTEvent<'_> {
682        match self {
683            VTOwnedEvent::Raw(s) => VTEvent::Raw(s),
684            VTOwnedEvent::C0(b) => VTEvent::C0(*b),
685            VTOwnedEvent::Esc(esc) => VTEvent::Esc(*esc),
686            VTOwnedEvent::EscInvalid(esc_invalid) => VTEvent::EscInvalid(*esc_invalid),
687            VTOwnedEvent::Ss2(ss2) => VTEvent::Ss2(SS2 { char: ss2.char }),
688            VTOwnedEvent::Ss3(ss3) => VTEvent::Ss3(SS3 { char: ss3.char }),
689            VTOwnedEvent::Csi(csi) => VTEvent::Csi(CSI {
690                private: csi.private,
691                params: csi.params.borrow(),
692                intermediates: csi.intermediates,
693                final_byte: csi.final_byte,
694            }),
695            VTOwnedEvent::DcsStart(dcs_start) => VTEvent::DcsStart(DCS {
696                private: dcs_start.private,
697                params: dcs_start.params.borrow(),
698                intermediates: dcs_start.intermediates,
699                final_byte: dcs_start.final_byte,
700            }),
701            VTOwnedEvent::DcsData(s) => VTEvent::DcsData(s),
702            VTOwnedEvent::DcsEnd(s) => VTEvent::DcsEnd(s),
703            VTOwnedEvent::DcsCancel => VTEvent::DcsCancel,
704            VTOwnedEvent::OscStart => VTEvent::OscStart,
705            VTOwnedEvent::OscData(s) => VTEvent::OscData(s),
706            VTOwnedEvent::OscEnd { data, used_bel } => VTEvent::OscEnd {
707                data,
708                used_bel: *used_bel,
709            },
710            VTOwnedEvent::OscCancel => VTEvent::OscCancel,
711        }
712    }
713}
714
715/// An invalid escape sequence.
716#[cfg_attr(feature = "serde", derive(serde::Serialize))]
717#[derive(Clone, Copy, PartialEq, Eq)]
718pub enum EscInvalid {
719    One(u8),
720    Two(u8, u8),
721    Three(u8, u8, u8),
722    Four(u8, u8, u8, u8),
723}
724
725impl std::fmt::Debug for EscInvalid {
726    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
727        match self {
728            EscInvalid::One(b) => write!(f, "EscInvalid(1B {b:02X})")?,
729            EscInvalid::Two(b1, b2) => write!(f, "EscInvalid(1B {b1:02X} {b2:02X})")?,
730            EscInvalid::Three(b1, b2, b3) => {
731                write!(f, "EscInvalid(1B {b1:02X} {b2:02X} {b3:02X})")?
732            }
733            EscInvalid::Four(b1, b2, b3, b4) => {
734                write!(f, "EscInvalid(1B {b1:02X} {b2:02X} {b3:02X} {b4:02X})")?
735            }
736        }
737        Ok(())
738    }
739}
740
741#[cfg_attr(feature = "serde", derive(serde::Serialize))]
742#[derive(Clone, Copy, PartialEq, Eq)]
743pub struct Esc {
744    pub intermediates: VTIntermediate,
745    pub private: Option<u8>,
746    pub final_byte: u8,
747}
748
749impl std::fmt::Debug for Esc {
750    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
751        write!(f, "Esc(")?;
752        if let Some(p) = self.private {
753            write!(f, "{:?}, ", p as char)?;
754        }
755        write!(f, "{:?}, ", self.intermediates)?;
756        if let Ok(c) = AsciiControl::try_from(self.final_byte as char) {
757            write!(f, "{c})")?;
758        } else {
759            write!(f, "{})", self.final_byte as char)?;
760        }
761        Ok(())
762    }
763}
764
765#[cfg_attr(feature = "serde", derive(serde::Serialize))]
766#[derive(Clone, Copy, PartialEq, Eq)]
767pub struct SS2 {
768    pub char: u8,
769}
770
771impl std::fmt::Debug for SS2 {
772    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
773        write!(f, "Ss2(")?;
774        if let Ok(c) = AsciiControl::try_from(self.char as char) {
775            write!(f, "{c})")?;
776        } else {
777            write!(f, "{:?})", self.char as char)?;
778        }
779        Ok(())
780    }
781}
782
783#[cfg_attr(feature = "serde", derive(serde::Serialize))]
784#[derive(Clone, Copy, PartialEq, Eq)]
785pub struct SS3 {
786    pub char: u8,
787}
788
789impl std::fmt::Debug for SS3 {
790    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
791        write!(f, "Ss3(")?;
792        if let Ok(c) = AsciiControl::try_from(self.char as char) {
793            write!(f, "{c})")?;
794        } else {
795            write!(f, "{:?})", self.char as char)?;
796        }
797        Ok(())
798    }
799}
800
801#[cfg_attr(feature = "serde", derive(serde::Serialize))]
802#[derive(Clone, PartialEq, Eq)]
803pub struct CSI<'a> {
804    pub private: Option<u8>,
805    pub params: ParamBuf<'a>,
806    pub intermediates: VTIntermediate,
807    pub final_byte: u8,
808}
809
810impl<'a> std::fmt::Debug for CSI<'a> {
811    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
812        write!(f, "Csi(")?;
813        if let Some(p) = self.private {
814            write!(f, "{:?}, ", p as char)?;
815        }
816        for param in &self.params {
817            write!(f, "'")?;
818            fmt_utf8_bytes_simple(f, param)?;
819            write!(f, "', ")?;
820        }
821        write!(f, "{:?}, ", self.intermediates)?;
822        write!(f, "{:?})", self.final_byte as char)?;
823        Ok(())
824    }
825}
826
827#[cfg_attr(feature = "serde", derive(serde::Serialize))]
828#[derive(Clone, PartialEq, Eq)]
829pub struct DCS<'a> {
830    pub private: Option<u8>,
831    pub params: ParamBuf<'a>,
832    pub intermediates: VTIntermediate,
833    pub final_byte: u8,
834}
835
836impl<'a> std::fmt::Debug for DCS<'a> {
837    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
838        write!(f, "DcsStart(")?;
839        if let Some(p) = self.private {
840            write!(f, "{:?}, ", p as char)?;
841        }
842        for param in &self.params {
843            write!(f, "'")?;
844            fmt_utf8_bytes_simple(f, param)?;
845            write!(f, "', ")?;
846        }
847        write!(f, "{:?}, ", self.intermediates)?;
848        write!(f, "{})", self.final_byte as char)?;
849        Ok(())
850    }
851}
852
853#[cfg_attr(feature = "serde", derive(serde::Serialize))]
854#[derive(Clone, PartialEq, Eq)]
855pub struct CSIOwned {
856    pub private: Option<u8>,
857    pub params: ParamBufOwned,
858    pub intermediates: VTIntermediate,
859    pub final_byte: u8,
860}
861
862impl std::fmt::Debug for CSIOwned {
863    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
864        write!(f, "Csi(")?;
865        if let Some(p) = self.private {
866            write!(f, "{:?}", p as char)?;
867        }
868        for param in &self.params {
869            write!(f, ", '")?;
870            fmt_utf8_bytes_simple(f, param)?;
871            write!(f, "'")?;
872        }
873        write!(f, ", {:?}", self.intermediates)?;
874        write!(f, ", {:?})", self.final_byte as char)?;
875        Ok(())
876    }
877}
878
879#[cfg_attr(feature = "serde", derive(serde::Serialize))]
880#[derive(Clone, PartialEq, Eq)]
881pub struct DCSOwned {
882    pub private: Option<u8>,
883    pub params: ParamBufOwned,
884    pub intermediates: VTIntermediate,
885    pub final_byte: u8,
886}
887
888impl std::fmt::Debug for DCSOwned {
889    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
890        write!(f, "DcsStart(")?;
891        if let Some(p) = self.private {
892            write!(f, "{:?}", p as char)?;
893        }
894        for param in &self.params {
895            write!(f, ", '")?;
896            fmt_utf8_bytes_simple(f, param)?;
897            write!(f, "'")?;
898        }
899        write!(f, ", {:?}", self.intermediates)?;
900        write!(f, ", {})", self.final_byte as char)?;
901        Ok(())
902    }
903}
904
905#[cfg(test)]
906mod test {
907    use super::*;
908
909    #[test]
910    fn test_numeric_param_buf() {
911        let param_buf = ParamBufOwned::new(&[b"1:2:3", b"4", b":"]);
912        let numeric_param_buf = param_buf.numeric();
913        assert_eq!(
914            numeric_param_buf.into_iter().flatten().collect::<Vec<_>>(),
915            vec![Some(1), Some(2), Some(3), Some(4), None, None]
916        );
917    }
918}