vt_push_parser/
event.rs

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