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