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