Skip to main content

vt_push_parser/
event.rs

1//! Event types.
2use std::{io, iter::Map};
3
4use crate::AsciiControl;
5
6/// Helper function to format UTF-8 chunks with ASCII control character handling
7fn fmt_utf8_bytes_with_ascii_control(
8    f: &mut std::fmt::Formatter<'_>,
9    bytes: &[u8],
10) -> std::fmt::Result {
11    for chunk in bytes.utf8_chunks() {
12        for c in chunk.valid().chars() {
13            if let Ok(c) = AsciiControl::try_from(c) {
14                write!(f, "{c}")?;
15            } else {
16                write!(f, "{c}")?;
17            }
18        }
19        if !chunk.invalid().is_empty() {
20            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
21        }
22    }
23    Ok(())
24}
25
26/// Helper function to format UTF-8 chunks for parameters (simple formatting)
27fn fmt_utf8_bytes_simple(f: &mut std::fmt::Formatter<'_>, bytes: &[u8]) -> std::fmt::Result {
28    for chunk in bytes.utf8_chunks() {
29        write!(f, "{}", chunk.valid())?;
30        if !chunk.invalid().is_empty() {
31            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
32        }
33    }
34    Ok(())
35}
36
37#[cfg_attr(feature = "serde", derive(serde::Serialize))]
38#[derive(Default, Clone, Copy, PartialEq, Eq, Hash)]
39pub struct VTIntermediate {
40    pub(crate) data: [u8; 2],
41}
42
43impl VTIntermediate {
44    pub const fn empty() -> Self {
45        Self { data: [0, 0] }
46    }
47
48    pub const fn one(c: u8) -> Self {
49        assert!(c >= 0x20 && c <= 0x2F);
50        Self { data: [c, 0] }
51    }
52
53    pub const fn two(c1: u8, c2: u8) -> Self {
54        assert!(c1 >= 0x20 && c1 <= 0x2F);
55        assert!(c2 >= 0x20 && c2 <= 0x2F);
56        Self { data: [c1, c2] }
57    }
58
59    pub fn has(&self, c: u8) -> bool {
60        self.data[0] == c || self.data[1] == c
61    }
62
63    pub fn clear(&mut self) {
64        self.data[0] = 0;
65        self.data[1] = 0;
66    }
67
68    pub fn is_empty(&self) -> bool {
69        self.data[0] == 0 && self.data[1] == 0
70    }
71
72    pub fn len(&self) -> usize {
73        self.data.iter().filter(|&&c| c != 0).count()
74    }
75
76    pub fn first(&self) -> Option<u8> {
77        if self.data[0] != 0 {
78            Some(self.data[0])
79        } else {
80            None
81        }
82    }
83
84    pub fn second(&self) -> Option<u8> {
85        if self.data[1] != 0 {
86            Some(self.data[1])
87        } else {
88            None
89        }
90    }
91
92    #[must_use]
93    pub fn push(&mut self, c: u8) -> bool {
94        if !(0x20..=0x2F).contains(&c) {
95            return false;
96        }
97
98        // Invalid duplicate intermediate
99        if self.data[0] == c {
100            return false;
101        }
102
103        if self.data[0] == 0 {
104            self.data[0] = c;
105            true
106        } else if self.data[1] == 0 {
107            self.data[1] = c;
108            true
109        } else {
110            false
111        }
112    }
113
114    pub const fn const_eq(&self, other: &Self) -> bool {
115        self.data[0] == other.data[0] && self.data[1] == other.data[1]
116    }
117
118    pub fn byte_len(&self) -> usize {
119        self.data.iter().filter(|&&c| c != 0).count()
120    }
121}
122
123impl AsRef<[u8]> for VTIntermediate {
124    fn as_ref(&self) -> &[u8] {
125        &self.data[..self.byte_len()]
126    }
127}
128
129impl std::fmt::Debug for VTIntermediate {
130    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131        // Inefficient
132        write!(f, "'")?;
133        for c in self.data.iter() {
134            if *c == 0 {
135                break;
136            }
137            write!(f, "{}", *c as char)?;
138        }
139        write!(f, "'")?;
140        Ok(())
141    }
142}
143
144/// A single parameter, as collected by the parser.
145///
146/// A fixed-capacity inline buffer of [`MAX_PARAM_LEN`] bytes.
147#[derive(Clone, Copy)]
148pub struct Param {
149    data: [u8; MAX_PARAM_LEN],
150    len: u8,
151    /// Whether any byte was dropped (per-parameter overflow).
152    overflowed: bool,
153}
154
155impl Param {
156    /// An empty parameter. `const`-callable and usable in statics.
157    pub const EMPTY: Self = Self {
158        data: [0; MAX_PARAM_LEN],
159        len: 0,
160        overflowed: false,
161    };
162
163    /// Whether any byte was dropped because the parameter exceeded
164    /// [`MAX_PARAM_LEN`] bytes.
165    #[inline]
166    pub fn overflowed(&self) -> bool {
167        self.overflowed
168    }
169
170    /// Append a byte, dropping bytes past [`MAX_PARAM_LEN`].
171    #[inline]
172    pub fn push(&mut self, b: u8) {
173        if (self.len as usize) < MAX_PARAM_LEN {
174            self.data[self.len as usize] = b;
175            self.len += 1;
176        } else {
177            self.overflowed = true;
178        }
179    }
180
181    /// Append the bytes of a slice, dropping bytes past [`MAX_PARAM_LEN`].
182    #[inline]
183    pub fn extend_from_slice(&mut self, bytes: &[u8]) {
184        for &b in bytes {
185            self.push(b);
186        }
187    }
188
189    /// Drop all bytes.
190    #[inline]
191    pub fn clear(&mut self) {
192        self.len = 0;
193        self.overflowed = false;
194    }
195
196    /// The collected bytes.
197    #[inline]
198    pub fn as_slice(&self) -> &[u8] {
199        &self.data[..self.len as usize]
200    }
201}
202
203impl std::ops::Deref for Param {
204    type Target = [u8];
205
206    #[inline]
207    fn deref(&self) -> &[u8] {
208        self.as_slice()
209    }
210}
211
212impl AsRef<[u8]> for Param {
213    #[inline]
214    fn as_ref(&self) -> &[u8] {
215        self.as_slice()
216    }
217}
218
219impl PartialEq for Param {
220    fn eq(&self, other: &Self) -> bool {
221        self.as_slice() == other.as_slice()
222    }
223}
224
225impl Eq for Param {}
226
227impl std::hash::Hash for Param {
228    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
229        self.as_slice().hash(state)
230    }
231}
232
233impl std::fmt::Debug for Param {
234    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        f.debug_list().entries(self.as_slice()).finish()
236    }
237}
238
239/// The maximum number of parameters collected for a single escape sequence.
240pub const MAX_PARAMS: usize = 128;
241
242/// The maximum number of bytes collected for a single parameter. This is the
243/// same as the inline capacity of [`Param`].
244pub const MAX_PARAM_LEN: usize = 32;
245
246/// The maximum number of parameter bytes (excluding `;` separators) collected
247/// for a single escape sequence.
248pub const MAX_PARAM_BYTES: usize = 1024;
249
250/// Fixed-capacity, inline parameter storage for the parser hot path.
251///
252/// Sequences may be split across `feed_with` calls, so parameters cannot be
253/// borrowed from the input and must be buffered by the parser. This type does
254/// so with a bounded, inline arena so that parsing is allocation-free (and
255/// `memcpy`-only) for all input:
256///
257/// - at most [`MAX_PARAMS`] parameters per sequence;
258/// - at most [`MAX_PARAM_LEN`] bytes per parameter;
259/// - at most [`MAX_PARAM_BYTES`] parameter bytes in total per sequence.
260#[derive(Clone, Copy)]
261pub struct ParamList {
262    /// Length of each collected parameter.
263    lens: [u8; MAX_PARAMS],
264    /// Concatenated parameter bytes.
265    data: [u8; MAX_PARAM_BYTES],
266    /// Number of collected parameters.
267    count: u16,
268    /// Number of used bytes in `data`.
269    used: u16,
270    /// Whether anything was dropped (per-parameter, or sequence-wide).
271    overflowed: bool,
272}
273
274impl ParamList {
275    /// An empty list. `const`-callable and usable in statics.
276    pub const EMPTY: Self = Self {
277        lens: [0; MAX_PARAMS],
278        data: [0; MAX_PARAM_BYTES],
279        count: 0,
280        used: 0,
281        overflowed: false,
282    };
283
284    /// The number of collected parameters.
285    #[inline]
286    pub fn len(&self) -> usize {
287        self.count as usize
288    }
289
290    /// Whether no parameters have been collected.
291    #[inline]
292    pub fn is_empty(&self) -> bool {
293        self.count == 0
294    }
295
296    /// The collected parameters, as byte slices.
297    #[inline]
298    pub fn iter(&self) -> ParamListIter<'_> {
299        let (data, lens, count) = ParamSource::Inline(self).parts();
300        ParamListIter {
301            data,
302            lens,
303            count,
304            index: 0,
305            offset: 0,
306        }
307    }
308
309    /// Whether any parameter bytes were dropped: bytes past a parameter's
310    /// [`MAX_PARAM_LEN`] cap, or parameters past the [`MAX_PARAMS`] /
311    /// [`MAX_PARAM_BYTES`] sequence caps.
312    #[inline]
313    pub fn overflowed(&self) -> bool {
314        self.overflowed
315    }
316
317    /// Record that something was dropped (crate-internal: the parser's
318    /// current-parameter buffer clamps per byte, before `push_param`).
319    #[inline]
320    pub(crate) fn mark_overflowed(&mut self) {
321        self.overflowed = true;
322    }
323
324    /// The parameter at `index`, if any.
325    #[inline]
326    pub fn get(&self, index: usize) -> Option<&[u8]> {
327        if index >= self.count as usize {
328            return None;
329        }
330        let offset: usize = self.lens[..index].iter().map(|&len| len as usize).sum();
331        let len = self.lens[index] as usize;
332        Some(&self.data[offset..offset + len])
333    }
334
335    /// The number of parameter bytes (excluding `;` separators).
336    #[inline]
337    pub fn byte_len(&self) -> usize {
338        self.used as usize + self.count.saturating_sub(1) as usize
339    }
340
341    /// Append a parameter, clamping on overflow (see the type docs).
342    ///
343    /// Bytes beyond [`MAX_PARAM_LEN`] within the current parameter, and any
344    /// parameter that does not fit the remaining sequence capacity, are
345    /// dropped; parsing continues normally. Sets
346    /// [`overflowed`](Self::overflowed) if anything was dropped.
347    #[inline]
348    pub fn push_param(&mut self, param: &[u8]) {
349        if param.len() > MAX_PARAM_LEN {
350            self.overflowed = true;
351        }
352        if self.count as usize >= MAX_PARAMS || self.used as usize >= MAX_PARAM_BYTES {
353            self.overflowed = true;
354            return;
355        }
356        let remaining = MAX_PARAM_BYTES - self.used as usize;
357        let len = param.len().min(MAX_PARAM_LEN).min(remaining);
358        if len < param.len() {
359            self.overflowed = true;
360        }
361        let start = self.used as usize;
362        self.data[start..start + len].copy_from_slice(&param[..len]);
363        self.lens[self.count as usize] = len as u8;
364        self.count += 1;
365        self.used += len as u16;
366    }
367
368    /// Drop all collected parameters.
369    #[inline]
370    pub fn clear(&mut self) {
371        self.count = 0;
372        self.used = 0;
373        self.overflowed = false;
374    }
375}
376
377impl PartialEq for ParamList {
378    fn eq(&self, other: &Self) -> bool {
379        // `data`/`lens` may contain stale bytes past `count`/`used`, so compare
380        // the logical contents only.
381        self.count == other.count && self.iter().eq(other.iter())
382    }
383}
384
385impl Eq for ParamList {}
386
387impl std::hash::Hash for ParamList {
388    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
389        // Hash the logical contents only, mirroring `PartialEq`: the raw
390        // arrays may contain stale bytes past `count`/`used`.
391        self.count.hash(state);
392        for param in self.iter() {
393            param.hash(state);
394        }
395    }
396}
397
398impl Default for ParamList {
399    fn default() -> Self {
400        Self::EMPTY
401    }
402}
403
404impl std::fmt::Debug for ParamList {
405    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
406        f.debug_list().entries(self.iter()).finish()
407    }
408}
409
410#[cfg(feature = "serde")]
411impl serde::Serialize for ParamList {
412    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
413        use serde::ser::SerializeSeq;
414        let mut seq = serializer.serialize_seq(Some(self.count as usize))?;
415        for param in self.iter() {
416            seq.serialize_element(param)?;
417        }
418        seq.end()
419    }
420}
421
422static EMPTY_PARAMS: ParamList = ParamList::EMPTY;
423
424/// The parameter storage backing a [`ParamBuf`]: either the parser's inline
425/// [`ParamList`] or the content-sized heap storage of a [`ParamBufOwned`].
426#[derive(Copy, Clone)]
427pub(crate) enum ParamSource<'a> {
428    Inline(&'a ParamList),
429    Owned(&'a ParamBufOwned),
430}
431
432impl<'a> ParamSource<'a> {
433    /// The concatenated parameter bytes, the per-parameter lengths and the
434    /// parameter count.
435    #[inline]
436    fn parts(self) -> (&'a [u8], &'a [u8], usize) {
437        match self {
438            ParamSource::Inline(list) => (
439                &list.data[..list.used as usize],
440                &list.lens[..list.count as usize],
441                list.count as usize,
442            ),
443            ParamSource::Owned(owned) => (
444                owned.data.as_deref().unwrap_or(&[]),
445                owned.lens.as_deref().unwrap_or(&[]),
446                owned.lens.as_ref().map_or(0, |lens| lens.len()),
447            ),
448        }
449    }
450
451    #[inline]
452    fn len(self) -> usize {
453        self.parts().2
454    }
455
456    #[inline]
457    fn is_empty(self) -> bool {
458        self.len() == 0
459    }
460
461    #[inline]
462    fn overflowed(self) -> bool {
463        match self {
464            ParamSource::Inline(list) => list.overflowed(),
465            ParamSource::Owned(owned) => owned.overflowed,
466        }
467    }
468
469    fn get(self, index: usize) -> Option<&'a [u8]> {
470        let (data, lens, count) = self.parts();
471        if index >= count {
472            return None;
473        }
474        let offset: usize = lens[..index].iter().map(|&len| len as usize).sum();
475        let len = lens[index] as usize;
476        Some(&data[offset..offset + len])
477    }
478
479    #[inline]
480    fn byte_len(self) -> usize {
481        let (data, _, count) = self.parts();
482        data.len() + count.saturating_sub(1)
483    }
484
485    #[inline]
486    fn iter(self) -> ParamListIter<'a> {
487        let (data, lens, count) = self.parts();
488        ParamListIter {
489            data,
490            lens,
491            count,
492            index: 0,
493            offset: 0,
494        }
495    }
496}
497
498impl PartialEq for ParamSource<'_> {
499    fn eq(&self, other: &Self) -> bool {
500        self.iter().eq(other.iter())
501    }
502}
503
504impl Eq for ParamSource<'_> {}
505
506impl std::hash::Hash for ParamSource<'_> {
507    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
508        // Mirror `PartialEq`: hash the logical contents only.
509        self.len().hash(state);
510        for param in self.iter() {
511            param.hash(state);
512        }
513    }
514}
515
516impl std::fmt::Debug for ParamSource<'_> {
517    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
518        f.debug_list().entries(self.iter()).finish()
519    }
520}
521
522#[cfg(feature = "serde")]
523impl serde::Serialize for ParamSource<'_> {
524    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
525        use serde::ser::SerializeSeq;
526        let mut seq = serializer.serialize_seq(Some(self.len()))?;
527        for param in self.iter() {
528            seq.serialize_element(param)?;
529        }
530        seq.end()
531    }
532}
533
534/// The parameters of an escape sequence (CSI/DCS), as emitted by the parser.
535///
536/// Parameters are buffered by the parser because sequences may be split
537/// across `feed_with` calls. Storage is fixed-capacity and inline, which
538/// bounds what can be reported for extreme input:
539///
540/// - at most [`MAX_PARAMS`] parameters;
541/// - at most [`MAX_PARAM_LEN`] bytes per parameter;
542/// - at most [`MAX_PARAM_BYTES`] parameter bytes (separators excluded);
543///
544/// A `ParamBuf` either borrows the parser's inline storage or the
545/// content-sized storage of a [`ParamBufOwned`] (see [`ParamBufOwned::borrow`]);
546/// the limits above apply to both.
547#[cfg_attr(feature = "serde", derive(serde::Serialize))]
548#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
549#[repr(transparent)]
550pub struct ParamBuf<'a> {
551    pub(crate) params: ParamSource<'a>,
552}
553
554impl<'a> IntoIterator for ParamBuf<'a> {
555    type Item = &'a [u8];
556    type IntoIter = std::iter::Map<ParamListIter<'a>, fn(&'a [u8]) -> &'a [u8]>;
557    fn into_iter(self) -> Self::IntoIter {
558        self.params.iter().map(|p| p as &[u8])
559    }
560}
561
562impl<'a> IntoIterator for &ParamBuf<'a> {
563    type Item = &'a [u8];
564    type IntoIter = std::iter::Map<ParamListIter<'a>, fn(&'a [u8]) -> &'a [u8]>;
565    fn into_iter(self) -> Self::IntoIter {
566        self.params.iter().map(|p| p as &[u8])
567    }
568}
569
570impl<'a> ParamBuf<'a> {
571    pub const fn empty() -> Self {
572        ParamBuf {
573            params: ParamSource::Inline(&EMPTY_PARAMS),
574        }
575    }
576
577    /// A view over the parser's inline parameter storage.
578    pub(crate) const fn from_param_list(list: &'a ParamList) -> Self {
579        ParamBuf {
580            params: ParamSource::Inline(list),
581        }
582    }
583
584    pub fn len(&self) -> usize {
585        self.params.len()
586    }
587
588    pub fn is_empty(&self) -> bool {
589        self.params.is_empty()
590    }
591
592    pub fn get(&self, index: usize) -> Option<&[u8]> {
593        self.params.get(index)
594    }
595
596    pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
597        self.params.get(index).and_then(|p| {
598            std::str::from_utf8(p)
599                .ok()
600                .and_then(|s| s.parse::<T>().ok())
601        })
602    }
603
604    pub fn to_owned(&self) -> ParamBufOwned {
605        match self.params {
606            ParamSource::Inline(list) => ParamBufOwned::from_param_list(list),
607            ParamSource::Owned(owned) => owned.clone(),
608        }
609    }
610
611    /// Whether any parameter bytes were dropped by the capacity limits; see
612    /// the [`ParamBuf`] documentation.
613    pub fn overflowed(&self) -> bool {
614        self.params.overflowed()
615    }
616
617    pub fn byte_len(&self) -> usize {
618        self.params.byte_len()
619    }
620
621    pub fn numeric(&self) -> NumericParamBuf<'a> {
622        NumericParamBuf {
623            params: self.params,
624        }
625    }
626}
627
628/// Iterator over the parameters of a [`ParamList`] (and thus of [`ParamBuf`]
629/// and [`ParamBufOwned`]).
630///
631/// This type is nameable so that a matching iterator can be written against
632/// [`ParamBuf`] in downstream signatures; use `ParamList::iter`,
633/// `ParamBuf::into_iter` or `&ParamBufOwned::into_iter` to construct one.
634pub struct ParamListIter<'a> {
635    /// Concatenated parameter bytes.
636    data: &'a [u8],
637    /// Length of each parameter.
638    lens: &'a [u8],
639    /// Number of parameters.
640    count: usize,
641    index: usize,
642    offset: usize,
643}
644
645impl<'a> Iterator for ParamListIter<'a> {
646    type Item = &'a [u8];
647
648    #[inline]
649    fn next(&mut self) -> Option<Self::Item> {
650        if self.index >= self.count {
651            return None;
652        }
653        let len = self.lens[self.index] as usize;
654        let param = &self.data[self.offset..self.offset + len];
655        self.index += 1;
656        self.offset += len;
657        Some(param)
658    }
659
660    #[inline]
661    fn size_hint(&self) -> (usize, Option<usize>) {
662        let remaining = self.count - self.index;
663        (remaining, Some(remaining))
664    }
665}
666
667impl ExactSizeIterator for ParamListIter<'_> {}
668
669impl std::iter::FusedIterator for ParamListIter<'_> {}
670
671/// A view into a [`Param`] that contains only numeric parameters.
672#[derive(Debug, Copy, Clone, Default)]
673pub struct NumericParam<'a> {
674    pub(crate) param: &'a [u8],
675}
676
677impl<'a> NumericParam<'a> {
678    /// Try to parse the parameter as a single numeric value.
679    pub fn sole(&self) -> Option<u16> {
680        if !self.param.is_empty() && !self.param.contains(&b':') {
681            if let Ok(s) = std::str::from_utf8(self.param) {
682                s.parse::<u16>().ok()
683            } else {
684                None
685            }
686        } else {
687            None
688        }
689    }
690
691    /// Try to parse the first parameter as a single numeric value.
692    pub fn first(&self) -> Option<u16> {
693        self.into_iter().next().flatten()
694    }
695
696    pub fn is_empty(&self) -> bool {
697        self.param.is_empty()
698    }
699
700    pub fn len(&self) -> usize {
701        self.param.iter().filter(|p| **p == b':').count() + 1
702    }
703
704    /// Try to write the parameters to the given buffer, returning the written
705    /// slice if successful. If any parameters are not a single-numeric value,
706    /// writes a zero in that position.
707    ///
708    /// If the slice is not long enough, returns an error with the required
709    /// length.
710    pub fn try_write<'b>(&self, buf: &'b mut [u16]) -> Result<&'b [u16], usize> {
711        let len = self.len();
712        if buf.len() < len {
713            return Err(buf.len());
714        }
715        for (i, param) in self.into_iter().enumerate() {
716            buf[i] = param.unwrap_or(0);
717        }
718        Ok(&buf[..len])
719    }
720}
721
722impl<'a> IntoIterator for NumericParam<'a> {
723    type Item = Option<u16>;
724    type IntoIter = Map<std::slice::Split<'a, u8, fn(&u8) -> bool>, fn(&'a [u8]) -> Option<u16>>;
725    fn into_iter(self) -> Self::IntoIter {
726        let fn1: fn(&u8) -> bool = |c: &u8| *c == b':';
727        self.param.split(fn1).map(|p| {
728            if p.is_empty() {
729                None
730            } else {
731                std::str::from_utf8(p)
732                    .ok()
733                    .and_then(|s| s.parse::<u16>().ok())
734            }
735        })
736    }
737}
738
739/// A view into a [`ParamBuf`] that contains only numeric parameters.
740///
741/// Each parameter may contain zero or more numeric values, separated by colons.
742/// Empty parameters are interpreted as `None`.
743#[derive(Debug, Copy, Clone)]
744pub struct NumericParamBuf<'a> {
745    pub(crate) params: ParamSource<'a>,
746}
747
748impl<'a> IntoIterator for NumericParamBuf<'a> {
749    type Item = NumericParam<'a>;
750    type IntoIter = std::iter::Map<ParamListIter<'a>, fn(&'a [u8]) -> NumericParam<'a>>;
751    fn into_iter(self) -> Self::IntoIter {
752        self.params.iter().map(|p| NumericParam { param: p })
753    }
754}
755
756impl<'a> NumericParamBuf<'a> {
757    pub const fn empty() -> Self {
758        NumericParamBuf {
759            params: ParamSource::Inline(&EMPTY_PARAMS),
760        }
761    }
762
763    /// Try to write the parameters to the given buffer, returning the written
764    /// slice if successful. If any parameters are not a single-numeric value,
765    /// writes a zero in that position.
766    ///
767    /// If the slice is not long enough, returns an error with the required
768    /// length.
769    pub fn try_write<'b>(&self, buf: &'b mut [u16]) -> Result<&'b [u16], usize> {
770        let len = self.params.len();
771        if buf.len() < len {
772            return Err(buf.len());
773        }
774        for (i, param) in self.into_iter().enumerate() {
775            buf[i] = param.sole().unwrap_or(0);
776        }
777        Ok(&buf[..len])
778    }
779
780    pub fn get(&self, index: usize) -> Option<NumericParam<'a>> {
781        self.params.get(index).map(|p| NumericParam { param: p })
782    }
783
784    pub fn first(&self) -> Option<NumericParam<'a>> {
785        self.into_iter().next()
786    }
787
788    pub fn is_empty(&self) -> bool {
789        self.params.is_empty()
790    }
791
792    pub fn len(&self) -> usize {
793        self.params.len()
794    }
795}
796
797/// A union of all possible events that can be emitted by the parser, with
798/// borrowed data.
799#[cfg_attr(feature = "serde", derive(serde::Serialize))]
800#[derive(Clone, PartialEq, Eq, Hash)]
801pub enum VTEvent<'a> {
802    // Plain printable text from GROUND (coalesced)
803    Raw(&'a [u8]),
804
805    // C0 control (EXECUTE)
806    C0(u8),
807
808    // ESC final (with intermediates)
809    Esc(Esc),
810
811    // Invalid escape sequence
812    EscInvalid(EscInvalid),
813
814    // SS2
815    Ss2(SS2),
816
817    // SS3
818    Ss3(SS3),
819
820    // CSI short escape
821    Csi(CSI<'a>),
822
823    // DCS stream
824    DcsStart(DCS<'a>),
825    DcsData(&'a [u8]),
826    DcsEnd(&'a [u8]),
827    DcsCancel,
828
829    // OSC stream
830    OscStart,
831    OscData(&'a [u8]),
832    OscEnd {
833        data: &'a [u8],
834        /// Whether the BEL was used to end the OSC stream.
835        used_bel: bool,
836    },
837    OscCancel,
838}
839
840impl<'a> std::fmt::Debug for VTEvent<'a> {
841    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
842        use VTEvent::*;
843        match self {
844            Raw(s) => {
845                write!(f, "Raw('")?;
846                fmt_utf8_bytes_with_ascii_control(f, s)?;
847                write!(f, "')")?;
848                Ok(())
849            }
850            EscInvalid(esc_invalid) => esc_invalid.fmt(f),
851            C0(b) => write!(f, "C0({b:02x})"),
852            Esc(esc) => esc.fmt(f),
853            Ss2(ss2) => ss2.fmt(f),
854            Ss3(ss3) => ss3.fmt(f),
855            Csi(csi) => csi.fmt(f),
856            DcsStart(dcs_start) => dcs_start.fmt(f),
857            DcsData(s) | DcsEnd(s) => {
858                if matches!(self, DcsEnd(..)) {
859                    write!(f, "DcsEnd('")?;
860                } else {
861                    write!(f, "DcsData('")?;
862                }
863                fmt_utf8_bytes_with_ascii_control(f, s)?;
864                write!(f, "')")?;
865                Ok(())
866            }
867            DcsCancel => write!(f, "DcsCancel"),
868            OscStart => write!(f, "OscStart"),
869            OscData(s) | OscEnd { data: s, .. } => {
870                if matches!(self, OscEnd { .. }) {
871                    write!(f, "OscEnd('")?;
872                } else {
873                    write!(f, "OscData('")?;
874                }
875                fmt_utf8_bytes_with_ascii_control(f, s)?;
876                write!(f, "')")?;
877                Ok(())
878            }
879            OscCancel => write!(f, "OscCancel"),
880        }
881    }
882}
883
884impl<'a> VTEvent<'a> {
885    pub fn csi(&self) -> Option<CSI<'a>> {
886        match self {
887            VTEvent::Csi(csi) => Some(CSI {
888                private: csi.private,
889                params: csi.params,
890                intermediates: csi.intermediates,
891                final_byte: csi.final_byte,
892            }),
893            _ => None,
894        }
895    }
896
897    pub fn byte_len(&self) -> usize {
898        use VTEvent::*;
899
900        match self {
901            Raw(s) => s.len(),
902            C0(_) => 1,
903            Esc(esc) => esc.intermediates.len() + 2 + esc.private.is_some() as usize,
904            EscInvalid(esc_invalid) => {
905                use self::EscInvalid::*;
906                match esc_invalid {
907                    One(..) => 2,
908                    Two(..) => 3,
909                    Three(..) => 4,
910                    Four(..) => 5,
911                }
912            }
913            Ss2(_) => 3,
914            Ss3(_) => 3,
915            Csi(csi) => {
916                csi.private.is_some() as usize
917                    + csi.params.byte_len()
918                    + csi.intermediates.byte_len()
919                    + 3
920            }
921            DcsStart(dcs_start) => {
922                dcs_start.private.is_some() as usize
923                    + dcs_start.params.byte_len()
924                    + dcs_start.intermediates.byte_len()
925                    + 3
926            }
927            DcsData(s) => s.len(),
928            DcsEnd(s) => s.len() + 2,
929            DcsCancel => 1,
930            OscStart => 2,
931            OscData(s) => s.len(),
932            OscEnd { data, used_bel } => {
933                if *used_bel {
934                    data.len() + 1
935                } else {
936                    data.len() + 2
937                }
938            }
939            OscCancel => 1,
940        }
941    }
942
943    /// Encode the event into the provided buffer, returning the number of bytes
944    /// required for the escape sequence in either `Ok(n)` or `Err(n)`.
945    ///
946    /// Note that some events may have multiple possible encodings, so this method
947    /// may decide to choose whichever is more efficient.
948    pub fn encode(&self, mut buf: &mut [u8]) -> Result<usize, usize> {
949        use crate::{BEL, CAN, CSI, DCS, ESC, OSC, SS2, SS3, ST_FINAL};
950        use VTEvent::*;
951
952        let len = self.byte_len();
953
954        if len > buf.len() {
955            return Err(len);
956        }
957
958        match self {
959            Raw(s) | OscData(s) | DcsData(s) => {
960                buf[..s.len()].copy_from_slice(s);
961            }
962            EscInvalid(esc_invalid) => {
963                use self::EscInvalid::*;
964                buf[0] = ESC;
965                match esc_invalid {
966                    One(b) => buf[1] = *b,
967                    Two(b1, b2) => {
968                        buf[1] = *b1;
969                        buf[2] = *b2;
970                    }
971                    Three(b1, b2, b3) => {
972                        buf[1] = *b1;
973                        buf[2] = *b2;
974                        buf[3] = *b3;
975                    }
976                    Four(b1, b2, b3, b4) => {
977                        buf[1] = *b1;
978                        buf[2] = *b2;
979                        buf[3] = *b3;
980                        buf[4] = *b4;
981                    }
982                }
983            }
984            OscCancel | DcsCancel => {
985                buf[0] = CAN;
986            }
987            C0(b) => {
988                buf[0] = *b;
989            }
990            Ss2(ss2) => {
991                buf[0] = ESC;
992                buf[1] = SS2;
993                buf[2] = ss2.char;
994            }
995            Ss3(ss3) => {
996                buf[0] = ESC;
997                buf[1] = SS3;
998                buf[2] = ss3.char;
999            }
1000            Esc(esc) => {
1001                buf[0] = ESC;
1002                if let Some(p) = esc.private {
1003                    buf[1] = p;
1004                    buf = &mut buf[1..];
1005                }
1006                buf[1..esc.intermediates.len() + 1]
1007                    .copy_from_slice(&esc.intermediates.data[..esc.intermediates.len()]);
1008                buf[esc.intermediates.len() + 1] = esc.final_byte;
1009            }
1010            Csi(csi) => {
1011                buf[0] = ESC;
1012                buf[1] = CSI;
1013                buf = &mut buf[2..];
1014                if let Some(p) = csi.private {
1015                    buf[0] = p;
1016                    buf = &mut buf[1..];
1017                }
1018                let mut params = csi.params.into_iter();
1019                if let Some(param) = params.next() {
1020                    buf[..param.len()].copy_from_slice(param);
1021                    buf = &mut buf[param.len()..];
1022                    for param in params {
1023                        buf[0] = b';';
1024                        buf = &mut buf[1..];
1025                        buf[..param.len()].copy_from_slice(param);
1026                        buf = &mut buf[param.len()..];
1027                    }
1028                }
1029                buf[..csi.intermediates.len()]
1030                    .copy_from_slice(&csi.intermediates.data[..csi.intermediates.len()]);
1031                buf[csi.intermediates.len()] = csi.final_byte;
1032            }
1033            DcsStart(dcs_start) => {
1034                buf[0] = ESC;
1035                buf[1] = DCS;
1036                buf = &mut buf[2..];
1037                if let Some(p) = dcs_start.private {
1038                    buf[0] = p;
1039                    buf = &mut buf[1..];
1040                }
1041                let mut params = dcs_start.params.into_iter();
1042                if let Some(param) = params.next() {
1043                    buf[..param.len()].copy_from_slice(param);
1044                    buf = &mut buf[param.len()..];
1045                    for param in params {
1046                        buf[0] = b';';
1047                        buf = &mut buf[1..];
1048                        buf[..param.len()].copy_from_slice(param);
1049                        buf = &mut buf[param.len()..];
1050                    }
1051                }
1052                buf[..dcs_start.intermediates.len()].copy_from_slice(
1053                    &dcs_start.intermediates.data[..dcs_start.intermediates.len()],
1054                );
1055                buf[dcs_start.intermediates.len()] = dcs_start.final_byte;
1056            }
1057            DcsEnd(data) => {
1058                buf[..data.len()].copy_from_slice(data);
1059                buf = &mut buf[data.len()..];
1060                buf[0] = ESC;
1061                buf[1] = ST_FINAL;
1062            }
1063            OscStart => {
1064                buf[0] = ESC;
1065                buf[1] = OSC;
1066            }
1067            OscEnd { data, used_bel } => {
1068                buf[..data.len()].copy_from_slice(data);
1069                buf = &mut buf[data.len()..];
1070                if *used_bel {
1071                    buf[0] = BEL;
1072                } else {
1073                    buf[0] = ESC;
1074                    buf[1] = ST_FINAL
1075                }
1076            }
1077        }
1078
1079        Ok(len)
1080    }
1081
1082    /// Encode the event into the provided writer, returning the number of bytes
1083    /// written.
1084    ///
1085    /// If the write fails for any reason, it is not possible to determine how
1086    /// many bytes were written.
1087    ///
1088    /// The order of writes is not specified and may change between versions of
1089    /// this crate.
1090    pub fn write_to(&self, mut writer: impl io::Write) -> Result<usize, io::Error> {
1091        use crate::{BEL, CAN, CSI, DCS, ESC, OSC, SS2, SS3, ST_FINAL};
1092
1093        use VTEvent::*;
1094        let mut len = 0;
1095        match self {
1096            Raw(s) | OscData(s) | DcsData(s) => {
1097                writer.write_all(s)?;
1098                len = s.len();
1099            }
1100            EscInvalid(esc_invalid) => {
1101                use self::EscInvalid::*;
1102                match esc_invalid {
1103                    One(b) => {
1104                        writer.write_all(&[ESC, *b])?;
1105                        len = 2;
1106                    }
1107                    Two(b1, b2) => {
1108                        writer.write_all(&[ESC, *b1, *b2])?;
1109                        len = 3;
1110                    }
1111                    Three(b1, b2, b3) => {
1112                        writer.write_all(&[ESC, *b1, *b2, *b3])?;
1113                        len = 4;
1114                    }
1115                    Four(b1, b2, b3, b4) => {
1116                        writer.write_all(&[ESC, *b1, *b2, *b3, *b4])?;
1117                        len = 5;
1118                    }
1119                }
1120            }
1121            OscCancel | DcsCancel => {
1122                writer.write_all(&[CAN])?;
1123                len = 1;
1124            }
1125            C0(b) => {
1126                writer.write_all(&[*b])?;
1127                len = 1;
1128            }
1129            Ss2(ss2) => {
1130                writer.write_all(&[ESC, SS2, ss2.char])?;
1131                len = 3;
1132            }
1133            Ss3(ss3) => {
1134                writer.write_all(&[ESC, SS3, ss3.char])?;
1135                len = 3;
1136            }
1137            Esc(esc) => {
1138                writer.write_all(&[ESC])?;
1139                len = 1;
1140                if let Some(p) = esc.private {
1141                    writer.write_all(&[p])?;
1142                    len = 2;
1143                }
1144                if !esc.intermediates.is_empty() {
1145                    writer.write_all(&esc.intermediates.data[..esc.intermediates.len()])?;
1146                    len += esc.intermediates.len();
1147                }
1148                writer.write_all(&[esc.final_byte])?;
1149                len += 1;
1150            }
1151            Csi(csi) => {
1152                writer.write_all(&[ESC, CSI])?;
1153                len = 2;
1154                if let Some(p) = csi.private {
1155                    writer.write_all(&[p])?;
1156                    len = 3;
1157                }
1158                let mut first = true;
1159                for param in csi.params {
1160                    if !first {
1161                        writer.write_all(b";")?;
1162                        len += 1;
1163                    } else {
1164                        first = false;
1165                    }
1166                    writer.write_all(param)?;
1167                    len += param.len();
1168                }
1169                if !csi.intermediates.is_empty() {
1170                    writer.write_all(&csi.intermediates.data[..csi.intermediates.len()])?;
1171                    len += csi.intermediates.len();
1172                }
1173                writer.write_all(&[csi.final_byte])?;
1174                len += 1;
1175            }
1176            DcsStart(dcs_start) => {
1177                writer.write_all(&[ESC, DCS])?;
1178                len = 2;
1179                if let Some(p) = dcs_start.private {
1180                    writer.write_all(&[p])?;
1181                    len = 3;
1182                }
1183                let mut first = true;
1184                for param in dcs_start.params {
1185                    if !first {
1186                        writer.write_all(b";")?;
1187                        len += 1;
1188                    } else {
1189                        first = false;
1190                    }
1191                    writer.write_all(param)?;
1192                    len += param.len();
1193                }
1194                if !dcs_start.intermediates.is_empty() {
1195                    writer.write_all(
1196                        &dcs_start.intermediates.data[..dcs_start.intermediates.len()],
1197                    )?;
1198                    len += dcs_start.intermediates.len();
1199                }
1200                writer.write_all(&[dcs_start.final_byte])?;
1201                len += 1;
1202            }
1203            DcsEnd(s) => {
1204                writer.write_all(s)?;
1205                len += s.len();
1206                writer.write_all(&[ESC, ST_FINAL])?;
1207                len += 2;
1208            }
1209            OscStart => {
1210                writer.write_all(&[ESC, OSC])?;
1211                len = 2;
1212            }
1213            OscEnd { data, used_bel } => {
1214                writer.write_all(data)?;
1215                if *used_bel {
1216                    writer.write_all(&[BEL])?;
1217                    len = 1 + data.len();
1218                } else {
1219                    writer.write_all(&[ESC, ST_FINAL])?;
1220                    len = 2 + data.len();
1221                }
1222            }
1223        }
1224        Ok(len)
1225    }
1226
1227    pub fn to_owned(&self) -> VTOwnedEvent {
1228        use VTEvent::*;
1229        match self {
1230            Raw(s) => VTOwnedEvent::Raw(s.to_vec()),
1231            C0(b) => VTOwnedEvent::C0(*b),
1232            Esc(esc) => VTOwnedEvent::Esc(*esc),
1233            EscInvalid(esc_invalid) => VTOwnedEvent::EscInvalid(*esc_invalid),
1234            Ss2(ss2) => VTOwnedEvent::Ss2(*ss2),
1235            Ss3(ss3) => VTOwnedEvent::Ss3(*ss3),
1236            Csi(csi) => VTOwnedEvent::Csi(CSIOwned {
1237                private: csi.private,
1238                params: csi.params.to_owned(),
1239                intermediates: csi.intermediates,
1240                final_byte: csi.final_byte,
1241            }),
1242            DcsStart(dcs_start) => VTOwnedEvent::DcsStart(DCSOwned {
1243                private: dcs_start.private,
1244                params: dcs_start.params.to_owned(),
1245                intermediates: dcs_start.intermediates,
1246                final_byte: dcs_start.final_byte,
1247            }),
1248            DcsData(s) => VTOwnedEvent::DcsData(s.to_vec()),
1249            DcsEnd(s) => VTOwnedEvent::DcsEnd(s.to_vec()),
1250            DcsCancel => VTOwnedEvent::DcsCancel,
1251            OscStart => VTOwnedEvent::OscStart,
1252            OscData(s) => VTOwnedEvent::OscData(s.to_vec()),
1253            OscEnd { data, used_bel } => VTOwnedEvent::OscEnd {
1254                data: data.to_vec(),
1255                used_bel: *used_bel,
1256            },
1257            OscCancel => VTOwnedEvent::OscCancel,
1258        }
1259    }
1260}
1261
1262/// Owned parameters of an escape sequence, as stored on [`VTOwnedEvent`].
1263///
1264/// This is the owned counterpart of [`ParamBuf`]. Unlike the parser's
1265/// fixed-capacity inline storage (see [`ParamBuf`]), it is sized to its
1266/// contents on the heap, so an owned copy of a small parameter list is
1267/// small; the limits documented on [`ParamBuf`] apply as before. It is a
1268/// convenience type: like other `to_owned()` data, it is intended for use
1269/// outside the parsing hot path.
1270///
1271/// Holding no parameters is allocation-free.
1272#[derive(Clone, PartialEq, Eq, Debug, Default)]
1273pub struct ParamBufOwned {
1274    pub(crate) data: Option<Box<[u8]>>,
1275    pub(crate) lens: Option<Box<[u8]>>,
1276    pub(crate) overflowed: bool,
1277}
1278
1279#[cfg(feature = "serde")]
1280impl serde::Serialize for ParamBufOwned {
1281    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1282        use serde::ser::SerializeMap;
1283        let mut map = serializer.serialize_map(Some(1))?;
1284        map.serialize_entry("params", &ParamSource::Owned(self))?;
1285        map.end()
1286    }
1287}
1288
1289impl ParamBufOwned {
1290    /// An owned copy of the logical contents of a [`ParamList`].
1291    pub(crate) fn from_param_list(list: &ParamList) -> Self {
1292        if list.count == 0 {
1293            return Self::EMPTY;
1294        }
1295        let data = &list.data[..list.used as usize];
1296        let lens = &list.lens[..list.count as usize];
1297        Self {
1298            data: Some(data.to_vec().into_boxed_slice()),
1299            lens: Some(lens.to_vec().into_boxed_slice()),
1300            overflowed: list.overflowed,
1301        }
1302    }
1303
1304    /// Empty `ParamBufOwned` with no allocation.
1305    pub const EMPTY: Self = Self {
1306        data: None,
1307        lens: None,
1308        overflowed: false,
1309    };
1310
1311    /// Create an empty `ParamBufOwned`.
1312    pub const fn empty() -> Self {
1313        Self::EMPTY
1314    }
1315
1316    /// Create a `ParamBufOwned` from a slice of slices.
1317    ///
1318    /// Parameters beyond the [`ParamBuf`] capacity limits are clamped; see the
1319    /// [`ParamBuf`] documentation for the exact semantics.
1320    pub fn new(params: &[&[u8]]) -> Self {
1321        let mut list = ParamList::EMPTY;
1322        for param in params {
1323            list.push_param(param);
1324        }
1325        Self::from_param_list(&list)
1326    }
1327
1328    pub fn len(&self) -> usize {
1329        self.lens.as_ref().map_or(0, |lens| lens.len())
1330    }
1331
1332    pub fn is_empty(&self) -> bool {
1333        self.len() == 0
1334    }
1335
1336    pub fn get(&self, index: usize) -> Option<&[u8]> {
1337        ParamSource::Owned(self).get(index)
1338    }
1339
1340    pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
1341        self.get(index).and_then(|p| {
1342            std::str::from_utf8(p)
1343                .ok()
1344                .and_then(|s| s.parse::<T>().ok())
1345        })
1346    }
1347
1348    /// Whether any parameter bytes were dropped by the capacity limits; see
1349    /// the [`ParamBuf`] documentation.
1350    pub fn overflowed(&self) -> bool {
1351        self.overflowed
1352    }
1353
1354    /// The number of parameter bytes (excluding `;` separators).
1355    pub fn byte_len(&self) -> usize {
1356        ParamSource::Owned(self).byte_len()
1357    }
1358
1359    pub fn borrow(&self) -> ParamBuf<'_> {
1360        ParamBuf {
1361            params: ParamSource::Owned(self),
1362        }
1363    }
1364
1365    pub fn numeric(&self) -> NumericParamBuf<'_> {
1366        NumericParamBuf {
1367            params: ParamSource::Owned(self),
1368        }
1369    }
1370}
1371
1372/// An owning iterator over the parameters of a [`ParamBufOwned`].
1373pub struct ParamBufOwnedIter {
1374    data: Box<[u8]>,
1375    lens: Box<[u8]>,
1376    index: usize,
1377    offset: usize,
1378}
1379
1380impl Iterator for ParamBufOwnedIter {
1381    type Item = Param;
1382
1383    #[inline]
1384    fn next(&mut self) -> Option<Self::Item> {
1385        if self.index >= self.lens.len() {
1386            return None;
1387        }
1388        let len = self.lens[self.index] as usize;
1389        let mut param = Param::EMPTY;
1390        param.extend_from_slice(&self.data[self.offset..self.offset + len]);
1391        self.index += 1;
1392        self.offset += len;
1393        Some(param)
1394    }
1395
1396    #[inline]
1397    fn size_hint(&self) -> (usize, Option<usize>) {
1398        let remaining = self.lens.len() - self.index;
1399        (remaining, Some(remaining))
1400    }
1401}
1402
1403impl ExactSizeIterator for ParamBufOwnedIter {}
1404
1405impl std::iter::FusedIterator for ParamBufOwnedIter {}
1406
1407impl IntoIterator for ParamBufOwned {
1408    type Item = Param;
1409    type IntoIter = ParamBufOwnedIter;
1410    fn into_iter(self) -> Self::IntoIter {
1411        ParamBufOwnedIter {
1412            data: self.data.unwrap_or_default(),
1413            lens: self.lens.unwrap_or_default(),
1414            index: 0,
1415            offset: 0,
1416        }
1417    }
1418}
1419
1420impl<'b> IntoIterator for &'b ParamBufOwned {
1421    type Item = &'b [u8];
1422    type IntoIter = ParamListIter<'b>;
1423    fn into_iter(self) -> Self::IntoIter {
1424        ParamSource::Owned(self).iter()
1425    }
1426}
1427
1428/// A union of all possible events that can be emitted by the parser, with owned
1429/// data.
1430#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1431#[derive(Clone, PartialEq, Eq)]
1432pub enum VTOwnedEvent {
1433    Raw(Vec<u8>),
1434    C0(u8),
1435    Esc(Esc),
1436    EscInvalid(EscInvalid),
1437    Ss2(SS2),
1438    Ss3(SS3),
1439    Csi(CSIOwned),
1440    DcsStart(DCSOwned),
1441    DcsData(Vec<u8>),
1442    DcsEnd(Vec<u8>),
1443    DcsCancel,
1444    OscStart,
1445    OscData(Vec<u8>),
1446    OscEnd { data: Vec<u8>, used_bel: bool },
1447    OscCancel,
1448}
1449
1450impl std::fmt::Debug for VTOwnedEvent {
1451    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1452        self.borrow().fmt(f)
1453    }
1454}
1455
1456impl VTOwnedEvent {
1457    pub fn borrow(&self) -> VTEvent<'_> {
1458        match self {
1459            VTOwnedEvent::Raw(s) => VTEvent::Raw(s),
1460            VTOwnedEvent::C0(b) => VTEvent::C0(*b),
1461            VTOwnedEvent::Esc(esc) => VTEvent::Esc(*esc),
1462            VTOwnedEvent::EscInvalid(esc_invalid) => VTEvent::EscInvalid(*esc_invalid),
1463            VTOwnedEvent::Ss2(ss2) => VTEvent::Ss2(SS2 { char: ss2.char }),
1464            VTOwnedEvent::Ss3(ss3) => VTEvent::Ss3(SS3 { char: ss3.char }),
1465            VTOwnedEvent::Csi(csi) => VTEvent::Csi(CSI {
1466                private: csi.private,
1467                params: csi.params.borrow(),
1468                intermediates: csi.intermediates,
1469                final_byte: csi.final_byte,
1470            }),
1471            VTOwnedEvent::DcsStart(dcs_start) => VTEvent::DcsStart(DCS {
1472                private: dcs_start.private,
1473                params: dcs_start.params.borrow(),
1474                intermediates: dcs_start.intermediates,
1475                final_byte: dcs_start.final_byte,
1476            }),
1477            VTOwnedEvent::DcsData(s) => VTEvent::DcsData(s),
1478            VTOwnedEvent::DcsEnd(s) => VTEvent::DcsEnd(s),
1479            VTOwnedEvent::DcsCancel => VTEvent::DcsCancel,
1480            VTOwnedEvent::OscStart => VTEvent::OscStart,
1481            VTOwnedEvent::OscData(s) => VTEvent::OscData(s),
1482            VTOwnedEvent::OscEnd { data, used_bel } => VTEvent::OscEnd {
1483                data,
1484                used_bel: *used_bel,
1485            },
1486            VTOwnedEvent::OscCancel => VTEvent::OscCancel,
1487        }
1488    }
1489}
1490
1491/// An invalid escape sequence.
1492#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1493#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1494pub enum EscInvalid {
1495    One(u8),
1496    Two(u8, u8),
1497    Three(u8, u8, u8),
1498    Four(u8, u8, u8, u8),
1499}
1500
1501impl std::fmt::Debug for EscInvalid {
1502    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1503        match self {
1504            EscInvalid::One(b) => write!(f, "EscInvalid(1B {b:02X})")?,
1505            EscInvalid::Two(b1, b2) => write!(f, "EscInvalid(1B {b1:02X} {b2:02X})")?,
1506            EscInvalid::Three(b1, b2, b3) => {
1507                write!(f, "EscInvalid(1B {b1:02X} {b2:02X} {b3:02X})")?
1508            }
1509            EscInvalid::Four(b1, b2, b3, b4) => {
1510                write!(f, "EscInvalid(1B {b1:02X} {b2:02X} {b3:02X} {b4:02X})")?
1511            }
1512        }
1513        Ok(())
1514    }
1515}
1516
1517#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1518#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1519pub struct Esc {
1520    pub intermediates: VTIntermediate,
1521    pub private: Option<u8>,
1522    pub final_byte: u8,
1523}
1524
1525impl std::fmt::Debug for Esc {
1526    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1527        write!(f, "Esc(")?;
1528        if let Some(p) = self.private {
1529            write!(f, "{:?}, ", p as char)?;
1530        }
1531        write!(f, "{:?}, ", self.intermediates)?;
1532        if let Ok(c) = AsciiControl::try_from(self.final_byte as char) {
1533            write!(f, "{c})")?;
1534        } else {
1535            write!(f, "{})", self.final_byte as char)?;
1536        }
1537        Ok(())
1538    }
1539}
1540
1541#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1542#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1543pub struct SS2 {
1544    pub char: u8,
1545}
1546
1547impl std::fmt::Debug for SS2 {
1548    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1549        write!(f, "Ss2(")?;
1550        if let Ok(c) = AsciiControl::try_from(self.char as char) {
1551            write!(f, "{c})")?;
1552        } else {
1553            write!(f, "{:?})", self.char as char)?;
1554        }
1555        Ok(())
1556    }
1557}
1558
1559#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1560#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1561pub struct SS3 {
1562    pub char: u8,
1563}
1564
1565impl std::fmt::Debug for SS3 {
1566    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1567        write!(f, "Ss3(")?;
1568        if let Ok(c) = AsciiControl::try_from(self.char as char) {
1569            write!(f, "{c})")?;
1570        } else {
1571            write!(f, "{:?})", self.char as char)?;
1572        }
1573        Ok(())
1574    }
1575}
1576
1577#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1578#[derive(Clone, PartialEq, Eq, Hash)]
1579pub struct CSI<'a> {
1580    pub private: Option<u8>,
1581    pub params: ParamBuf<'a>,
1582    pub intermediates: VTIntermediate,
1583    pub final_byte: u8,
1584}
1585
1586impl<'a> std::fmt::Debug for CSI<'a> {
1587    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1588        write!(f, "Csi(")?;
1589        if let Some(p) = self.private {
1590            write!(f, "{:?}, ", p as char)?;
1591        }
1592        for param in &self.params {
1593            write!(f, "'")?;
1594            fmt_utf8_bytes_simple(f, param)?;
1595            write!(f, "', ")?;
1596        }
1597        write!(f, "{:?}, ", self.intermediates)?;
1598        write!(f, "{:?})", self.final_byte as char)?;
1599        Ok(())
1600    }
1601}
1602
1603#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1604#[derive(Clone, PartialEq, Eq, Hash)]
1605pub struct DCS<'a> {
1606    pub private: Option<u8>,
1607    pub params: ParamBuf<'a>,
1608    pub intermediates: VTIntermediate,
1609    pub final_byte: u8,
1610}
1611
1612impl<'a> std::fmt::Debug for DCS<'a> {
1613    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1614        write!(f, "DcsStart(")?;
1615        if let Some(p) = self.private {
1616            write!(f, "{:?}, ", p as char)?;
1617        }
1618        for param in &self.params {
1619            write!(f, "'")?;
1620            fmt_utf8_bytes_simple(f, param)?;
1621            write!(f, "', ")?;
1622        }
1623        write!(f, "{:?}, ", self.intermediates)?;
1624        write!(f, "{})", self.final_byte as char)?;
1625        Ok(())
1626    }
1627}
1628
1629#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1630#[derive(Clone, PartialEq, Eq)]
1631pub struct CSIOwned {
1632    pub private: Option<u8>,
1633    pub params: ParamBufOwned,
1634    pub intermediates: VTIntermediate,
1635    pub final_byte: u8,
1636}
1637
1638impl std::fmt::Debug for CSIOwned {
1639    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1640        write!(f, "Csi(")?;
1641        if let Some(p) = self.private {
1642            write!(f, "{:?}", p as char)?;
1643        }
1644        for param in &self.params {
1645            write!(f, ", '")?;
1646            fmt_utf8_bytes_simple(f, param)?;
1647            write!(f, "'")?;
1648        }
1649        write!(f, ", {:?}", self.intermediates)?;
1650        write!(f, ", {:?})", self.final_byte as char)?;
1651        Ok(())
1652    }
1653}
1654
1655#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1656#[derive(Clone, PartialEq, Eq)]
1657pub struct DCSOwned {
1658    pub private: Option<u8>,
1659    pub params: ParamBufOwned,
1660    pub intermediates: VTIntermediate,
1661    pub final_byte: u8,
1662}
1663
1664impl std::fmt::Debug for DCSOwned {
1665    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1666        write!(f, "DcsStart(")?;
1667        if let Some(p) = self.private {
1668            write!(f, "{:?}", p as char)?;
1669        }
1670        for param in &self.params {
1671            write!(f, ", '")?;
1672            fmt_utf8_bytes_simple(f, param)?;
1673            write!(f, "'")?;
1674        }
1675        write!(f, ", {:?}", self.intermediates)?;
1676        write!(f, ", {})", self.final_byte as char)?;
1677        Ok(())
1678    }
1679}
1680
1681#[cfg(test)]
1682mod test {
1683    use super::*;
1684
1685    #[test]
1686    fn test_numeric_param_buf() {
1687        let param_buf = ParamBufOwned::new(&[b"1:2:3", b"4", b":"]);
1688        let numeric_param_buf = param_buf.numeric();
1689        assert_eq!(
1690            numeric_param_buf.into_iter().flatten().collect::<Vec<_>>(),
1691            vec![Some(1), Some(2), Some(3), Some(4), None, None]
1692        );
1693
1694        assert_eq!(numeric_param_buf.first().unwrap().sole(), None);
1695        assert_eq!(numeric_param_buf.first().unwrap().first(), Some(1));
1696        assert_eq!(numeric_param_buf.get(1).unwrap().sole(), Some(4));
1697        assert_eq!(numeric_param_buf.get(1).unwrap().first(), Some(4));
1698        assert_eq!(numeric_param_buf.get(2).unwrap().sole(), None);
1699        assert_eq!(numeric_param_buf.get(2).unwrap().first(), None);
1700
1701        assert_eq!(
1702            numeric_param_buf
1703                .try_write(&mut [0, 0, 0, 0, 0, 0])
1704                .unwrap(),
1705            &[0, 4, 0]
1706        );
1707        assert_eq!(
1708            numeric_param_buf
1709                .get(0)
1710                .unwrap()
1711                .try_write(&mut [0, 0, 0, 0, 0, 0])
1712                .unwrap(),
1713            &[1, 2, 3]
1714        );
1715    }
1716
1717    #[test]
1718    fn param_buf_owned_is_content_sized() {
1719        // No parameters: no heap storage at all.
1720        let empty = ParamBufOwned::new(&[]);
1721        assert!(empty.data.is_none());
1722        assert!(empty.lens.is_none());
1723        assert!(empty.is_empty());
1724        assert_eq!(empty.len(), 0);
1725
1726        // A small parameter list is stored in small heap allocations: the
1727        // bytes actually used ("1234" + "5"), not the parser's full inline
1728        // arena (MAX_PARAMS x MAX_PARAM_LEN).
1729        let small = ParamBufOwned::new(&[b"1234", b"5"]);
1730        assert_eq!(small.data.as_deref(), Some(&b"12345"[..]));
1731        assert_eq!(small.lens.as_deref(), Some(&[4, 1][..]));
1732        assert_eq!(small.len(), 2);
1733        assert_eq!(small.byte_len(), 6); // 5 bytes + 1 separator
1734        assert!(!small.overflowed());
1735
1736        // Storing many parameters still only stores what was collected.
1737        let strings: Vec<String> = (0..MAX_PARAMS as u32).map(|i| i.to_string()).collect();
1738        let slices: Vec<&[u8]> = strings.iter().map(|s| s.as_bytes()).collect();
1739        let many = ParamBufOwned::new(&slices);
1740        assert_eq!(many.len(), MAX_PARAMS);
1741        assert_eq!(many.get(0), Some(&b"0"[..]));
1742        assert_eq!(many.get(127), Some(&b"127"[..]));
1743        assert_eq!(many.byte_len(), 10 + 90 * 2 + 28 * 3 + 127);
1744    }
1745
1746    #[test]
1747    fn param_buf_owned_clamps_like_param_buf() {
1748        // Clamping applies to `ParamBufOwned::new` exactly as it does to the
1749        // parser: bytes past MAX_PARAM_LEN are dropped, params past the
1750        // sequence caps are dropped, and `overflowed()` reports both.
1751        let long = ParamBufOwned::new(&[&[b'7'; MAX_PARAM_LEN + 8][..]]);
1752        assert_eq!(long.len(), 1);
1753        assert_eq!(long.get(0).map(<[u8]>::len), Some(MAX_PARAM_LEN));
1754        assert!(long.overflowed());
1755
1756        let too_many_strings: Vec<String> = (0..(MAX_PARAMS + 8) as u32)
1757            .map(|i| i.to_string())
1758            .collect();
1759        let too_many_slices: Vec<&[u8]> = too_many_strings.iter().map(|s| s.as_bytes()).collect();
1760        let too_many = ParamBufOwned::new(&too_many_slices);
1761        assert_eq!(too_many.len(), MAX_PARAMS);
1762        assert!(too_many.overflowed());
1763
1764        // `ParamBuf::empty` and `ParamBufOwned::empty` agree.
1765        assert!(ParamBuf::empty().to_owned().is_empty());
1766        assert_eq!(ParamBuf::empty().to_owned(), ParamBufOwned::empty());
1767    }
1768
1769    #[test]
1770    fn param_buf_owned_views_match_parser_views() {
1771        // A view over owned storage behaves exactly like a view over the
1772        // parser's inline storage holding the same parameters.
1773        let owned = ParamBufOwned::new(&[b"1", b"22", b""]);
1774
1775        let mut list = ParamList::EMPTY;
1776        list.push_param(b"1");
1777        list.push_param(b"22");
1778        list.push_param(b"");
1779        let view = ParamBuf::from_param_list(&list);
1780
1781        assert_eq!(owned.borrow(), view);
1782        assert_eq!(owned.borrow().len(), view.len());
1783        assert_eq!(owned.borrow().byte_len(), view.byte_len());
1784        assert_eq!(
1785            owned.numeric().try_write(&mut [0; 4]).unwrap(),
1786            view.numeric().try_write(&mut [0; 4]).unwrap()
1787        );
1788        assert_eq!(
1789            owned.borrow().into_iter().collect::<Vec<_>>(),
1790            view.into_iter().collect::<Vec<_>>()
1791        );
1792        assert_eq!(
1793            (&owned).into_iter().collect::<Vec<_>>(),
1794            view.into_iter().collect::<Vec<_>>()
1795        );
1796        assert_eq!(format!("{:?}", owned.borrow()), format!("{:?}", view));
1797
1798        // `to_owned` of an owned-backed view is a deep copy.
1799        let copy = owned.borrow().to_owned();
1800        assert_eq!(copy, owned);
1801        assert_eq!(copy.get(1), Some(&b"22"[..]));
1802
1803        // The owning iterator yields the same parameters as `Param`s.
1804        fn param(bytes: &[u8]) -> Param {
1805            let mut p = Param::EMPTY;
1806            p.extend_from_slice(bytes);
1807            p
1808        }
1809        assert_eq!(
1810            owned.into_iter().collect::<Vec<_>>(),
1811            vec![param(b"1"), param(b"22"), Param::EMPTY]
1812        );
1813    }
1814
1815    #[test]
1816    fn param_buf_owned_overflowed_from_parser() {
1817        // Overflow survives the inline -> owned copy.
1818        let mut list = ParamList::EMPTY;
1819        list.push_param(&[b'7'; MAX_PARAM_LEN + 8]);
1820        list.push_param(b"1");
1821        let owned = ParamBuf::from_param_list(&list).to_owned();
1822        assert!(owned.overflowed());
1823        assert_eq!(owned.len(), 2);
1824        assert_eq!(owned.get(0).map(<[u8]>::len), Some(MAX_PARAM_LEN));
1825
1826        // No overflow in the source, no overflow in the copy.
1827        let mut list = ParamList::EMPTY;
1828        list.push_param(b"1");
1829        let owned = ParamBuf::from_param_list(&list).to_owned();
1830        assert!(!owned.overflowed());
1831    }
1832
1833    #[test]
1834    fn owned_param_size_is_pointer_sized_per_field() {
1835        // The owned buffer's inline footprint is two boxed slices (fat
1836        // pointers) plus a flag: a few words, far below the inline arena it
1837        // used to embed (lens + data + counts ~ 1.1 KiB).
1838        assert!(std::mem::size_of::<ParamBufOwned>() <= 5 * std::mem::size_of::<usize>());
1839        assert!(std::mem::size_of::<ParamList>() > 1024);
1840        assert!(std::mem::size_of::<ParamBufOwned>() * 16 < std::mem::size_of::<ParamList>());
1841    }
1842
1843    #[cfg(feature = "serde")]
1844    #[test]
1845    fn param_buf_owned_serde_shape_unchanged() {
1846        // The serialized shape is the same as before the `Box<[u8]>` change:
1847        // a map with a single "params" key holding the sequence.
1848        let owned = ParamBufOwned::new(&[b"1", b"22"]);
1849        let json = serde_json::to_string(&owned).unwrap();
1850        assert_eq!(json, r#"{"params":[[49],[50,50]]}"#);
1851    }
1852}