vt_push_parser/
event.rs

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