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