vt_push_parser/
event.rs

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