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,
188    DcsCancel,
189
190    // OSC stream
191    OscStart,
192    OscData(&'a [u8]),
193    OscEnd {
194        /// Whether the BEL was used to end the OSC stream.
195        used_bel: bool,
196    },
197    OscCancel,
198}
199
200impl<'a> std::fmt::Debug for VTEvent<'a> {
201    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202        use VTEvent::*;
203        match self {
204            Raw(s) => {
205                write!(f, "Raw('")?;
206                for chunk in s.utf8_chunks() {
207                    for c in chunk.valid().chars() {
208                        if let Ok(c) = AsciiControl::try_from(c) {
209                            write!(f, "{}", c)?;
210                        } else {
211                            write!(f, "{}", c)?;
212                        }
213                    }
214                    if !chunk.invalid().is_empty() {
215                        write!(f, "<{}>", hex::encode(chunk.invalid()))?;
216                    }
217                }
218                write!(f, "')")?;
219                Ok(())
220            }
221            C0(b) => write!(f, "C0({:02x})", b),
222            Esc {
223                intermediates,
224                final_byte,
225            } => {
226                write!(f, "Esc({:?}", intermediates)?;
227                write!(f, ", {})", *final_byte as char)?;
228                Ok(())
229            }
230            Ss2 { char } => write!(f, "Ss2({:?})", *char as char),
231            Ss3 { char } => write!(f, "Ss3({:?})", *char as char),
232            Csi {
233                private,
234                params,
235                intermediates,
236                final_byte,
237            } => {
238                write!(f, "Csi(")?;
239                if let Some(p) = private {
240                    write!(f, "{:?}", *p as char)?;
241                }
242                for param in params {
243                    write!(f, ", '")?;
244                    for chunk in param.utf8_chunks() {
245                        write!(f, "{}", chunk.valid())?;
246                        if !chunk.invalid().is_empty() {
247                            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
248                        }
249                    }
250                    write!(f, "'")?;
251                }
252                write!(f, ", {:?}", intermediates)?;
253                write!(f, ", {:?})", *final_byte as char)?;
254                Ok(())
255            }
256            DcsStart {
257                private,
258                params,
259                intermediates,
260                final_byte,
261            } => {
262                write!(f, "DcsStart(")?;
263                if let Some(p) = private {
264                    write!(f, "{:?}", *p as char)?;
265                }
266                for param in params {
267                    write!(f, ", '")?;
268                    for chunk in param.utf8_chunks() {
269                        write!(f, "{}", chunk.valid())?;
270                        if !chunk.invalid().is_empty() {
271                            write!(f, "<{}>", hex::encode(chunk.invalid()))?;
272                        }
273                    }
274                    write!(f, "'")?;
275                }
276                write!(f, ", {:?}", intermediates)?;
277                write!(f, ", {})", *final_byte as char)?;
278                Ok(())
279            }
280            DcsData(s) => {
281                write!(f, "DcsData('")?;
282                for chunk in s.utf8_chunks() {
283                    for c in chunk.valid().chars() {
284                        if let Ok(c) = AsciiControl::try_from(c) {
285                            write!(f, "{}", c)?;
286                        } else {
287                            write!(f, "{}", c)?;
288                        }
289                    }
290                    if !chunk.invalid().is_empty() {
291                        write!(f, "<{}>", hex::encode(chunk.invalid()))?;
292                    }
293                }
294                write!(f, "')")?;
295                Ok(())
296            }
297            DcsEnd => write!(f, "DcsEnd"),
298            DcsCancel => write!(f, "DcsCancel"),
299            OscStart => write!(f, "OscStart"),
300            OscData(s) => {
301                write!(f, "OscData('")?;
302                for chunk in s.utf8_chunks() {
303                    for c in chunk.valid().chars() {
304                        if let Ok(c) = AsciiControl::try_from(c) {
305                            write!(f, "{}", c)?;
306                        } else {
307                            write!(f, "{}", c)?;
308                        }
309                    }
310                    if !chunk.invalid().is_empty() {
311                        write!(f, "<{}>", hex::encode(chunk.invalid()))?;
312                    }
313                }
314                write!(f, "')")?;
315                Ok(())
316            }
317            OscEnd { .. } => {
318                write!(f, "OscEnd")?;
319                Ok(())
320            }
321            OscCancel => write!(f, "OscCancel"),
322        }
323    }
324}
325
326impl<'a> VTEvent<'a> {
327    pub fn csi(&self) -> Option<CSI> {
328        match self {
329            VTEvent::Csi {
330                private,
331                params,
332                intermediates,
333                final_byte,
334            } => Some(CSI {
335                private: *private,
336                params: *params,
337                intermediates: intermediates.clone(),
338                final_byte: *final_byte,
339            }),
340            _ => None,
341        }
342    }
343
344    pub fn byte_len(&self) -> usize {
345        use VTEvent::*;
346        let len = match self {
347            Raw(s) => s.len(),
348            C0(_) => 1,
349            Esc { intermediates, .. } => intermediates.len() + 2,
350            Ss2 { .. } => 3,
351            Ss3 { .. } => 3,
352            Csi {
353                private,
354                params,
355                intermediates,
356                ..
357            } => private.is_some() as usize + params.byte_len() + intermediates.byte_len() + 3,
358            DcsStart {
359                private,
360                params,
361                intermediates,
362                ..
363            } => private.is_some() as usize + params.byte_len() + intermediates.byte_len() + 3,
364            DcsData(s) => s.len(),
365            DcsEnd => 2,
366            DcsCancel => 1,
367            OscStart => 2,
368            OscData(s) => s.len(),
369            OscEnd { used_bel } => {
370                if *used_bel {
371                    1
372                } else {
373                    2
374                }
375            }
376            OscCancel => 1,
377        };
378        len
379    }
380
381    /// Encode the event into the provided buffer, returning the number of bytes
382    /// required for the escape sequence in either `Ok(n)` or `Err(n)`.
383    ///
384    /// Note that some events may have multiple possible encodings, so this method
385    /// may decide to choose whichever is more efficient.
386    pub fn encode(&self, mut buf: &mut [u8]) -> Result<usize, usize> {
387        use crate::{BEL, CAN, CSI, DCS, ESC, OSC, SS2, SS3, ST_FINAL};
388        use VTEvent::*;
389
390        let len = self.byte_len();
391
392        if len > buf.len() {
393            return Err(len);
394        }
395
396        match self {
397            Raw(s) | OscData(s) | DcsData(s) => {
398                buf[..s.len()].copy_from_slice(s);
399            }
400            OscCancel | DcsCancel => {
401                buf[0] = CAN;
402            }
403            C0(b) => {
404                buf[0] = *b;
405            }
406            Ss2 { char } => {
407                buf[0] = ESC;
408                buf[1] = SS2;
409                buf[2] = *char;
410            }
411            Ss3 { char } => {
412                buf[0] = ESC;
413                buf[1] = SS3;
414                buf[2] = *char;
415            }
416            Esc {
417                intermediates,
418                final_byte,
419            } => {
420                buf[0] = ESC;
421                buf[1..intermediates.len() + 1]
422                    .copy_from_slice(&intermediates.data[..intermediates.len()]);
423                buf[intermediates.len() + 1] = *final_byte;
424            }
425            Csi {
426                private,
427                params,
428                intermediates,
429                final_byte,
430            } => {
431                buf[0] = ESC;
432                buf[1] = CSI;
433                buf = &mut buf[2..];
434                if let Some(p) = private {
435                    buf[0] = *p;
436                    buf = &mut buf[1..];
437                }
438                let mut params = params.into_iter();
439                if let Some(param) = params.next() {
440                    buf[..param.len()].copy_from_slice(param);
441                    buf = &mut buf[param.len()..];
442                    for param in params {
443                        buf[0] = b';';
444                        buf = &mut buf[1..];
445                        buf[..param.len()].copy_from_slice(param);
446                        buf = &mut buf[param.len()..];
447                    }
448                }
449                buf[..intermediates.len()]
450                    .copy_from_slice(&intermediates.data[..intermediates.len()]);
451                buf[intermediates.len()] = *final_byte;
452            }
453            DcsStart {
454                private,
455                params,
456                intermediates,
457                final_byte,
458            } => {
459                buf[0] = ESC;
460                buf[1] = DCS;
461                buf = &mut buf[2..];
462                if let Some(p) = private {
463                    buf[0] = *p;
464                    buf = &mut buf[1..];
465                }
466                let mut params = params.into_iter();
467                if let Some(param) = params.next() {
468                    buf[..param.len()].copy_from_slice(param);
469                    buf = &mut buf[param.len()..];
470                    for param in params {
471                        buf[0] = b';';
472                        buf = &mut buf[1..];
473                        buf[..param.len()].copy_from_slice(param);
474                        buf = &mut buf[param.len()..];
475                    }
476                }
477                buf[..intermediates.len()]
478                    .copy_from_slice(&intermediates.data[..intermediates.len()]);
479                buf[intermediates.len()] = *final_byte;
480            }
481            DcsEnd => {
482                buf[0] = ESC;
483                buf[1] = ST_FINAL;
484            }
485            OscStart => {
486                buf[0] = ESC;
487                buf[1] = OSC;
488            }
489            OscEnd { used_bel } => {
490                if *used_bel {
491                    buf[0] = BEL;
492                } else {
493                    buf[0] = ESC;
494                    buf[1] = ST_FINAL
495                }
496            }
497        }
498
499        Ok(len)
500    }
501
502    pub fn to_owned(&self) -> VTOwnedEvent {
503        use VTEvent::*;
504        match self {
505            Raw(s) => VTOwnedEvent::Raw(s.to_vec()),
506            C0(b) => VTOwnedEvent::C0(*b),
507            Esc {
508                intermediates,
509                final_byte,
510            } => VTOwnedEvent::Esc {
511                intermediates: intermediates.clone(),
512                final_byte: *final_byte,
513            },
514            Ss2 { char } => VTOwnedEvent::Ss2 { char: *char },
515            Ss3 { char } => VTOwnedEvent::Ss3 { char: *char },
516            Csi {
517                private,
518                params,
519                intermediates,
520                final_byte,
521            } => VTOwnedEvent::Csi {
522                private: private.clone(),
523                params: params.to_owned(),
524                intermediates: intermediates.clone(),
525                final_byte: *final_byte,
526            },
527            DcsStart {
528                private,
529                params,
530                intermediates,
531                final_byte,
532            } => VTOwnedEvent::DcsStart {
533                private: private.clone(),
534                params: params.to_owned(),
535                intermediates: intermediates.clone(),
536                final_byte: *final_byte,
537            },
538            DcsData(s) => VTOwnedEvent::DcsData(s.to_vec()),
539            DcsEnd => VTOwnedEvent::DcsEnd,
540            DcsCancel => VTOwnedEvent::DcsCancel,
541            OscStart => VTOwnedEvent::OscStart,
542            OscData(s) => VTOwnedEvent::OscData(s.to_vec()),
543            OscEnd { used_bel } => VTOwnedEvent::OscEnd {
544                used_bel: *used_bel,
545            },
546            OscCancel => VTOwnedEvent::OscCancel,
547        }
548    }
549}
550
551#[derive(Clone, PartialEq, Eq)]
552pub struct ParamBufOwned {
553    pub(crate) params: Params,
554}
555
556impl IntoIterator for ParamBufOwned {
557    type Item = Param;
558    type IntoIter = <Params as IntoIterator>::IntoIter;
559    fn into_iter(self) -> Self::IntoIter {
560        self.params.into_iter()
561    }
562}
563
564impl<'b> IntoIterator for &'b ParamBufOwned {
565    type Item = &'b [u8];
566    type IntoIter = Map<std::slice::Iter<'b, Param>, fn(&Param) -> &[u8]>;
567    fn into_iter(self) -> Self::IntoIter {
568        self.params.iter().map(|p| p.as_slice())
569    }
570}
571
572impl ParamBufOwned {
573    pub fn len(&self) -> usize {
574        self.params.len()
575    }
576
577    pub fn is_empty(&self) -> bool {
578        self.params.is_empty()
579    }
580
581    pub fn get(&self, index: usize) -> Option<&[u8]> {
582        self.params.get(index).map(|p| p.as_slice())
583    }
584
585    pub fn try_parse<T: std::str::FromStr>(&self, index: usize) -> Option<T> {
586        self.params.get(index).and_then(|p| {
587            std::str::from_utf8(p.as_slice())
588                .ok()
589                .and_then(|s| s.parse::<T>().ok())
590        })
591    }
592
593    pub fn borrow(&self) -> ParamBuf<'_> {
594        ParamBuf {
595            params: &self.params,
596        }
597    }
598}
599
600#[derive(Clone, PartialEq, Eq)]
601pub enum VTOwnedEvent {
602    Raw(Vec<u8>),
603    C0(u8),
604    Esc {
605        intermediates: VTIntermediate,
606        final_byte: u8,
607    },
608    Ss2 {
609        char: u8,
610    },
611    Ss3 {
612        char: u8,
613    },
614    Csi {
615        private: Option<u8>,
616        params: ParamBufOwned,
617        intermediates: VTIntermediate,
618        final_byte: u8,
619    },
620    DcsStart {
621        private: Option<u8>,
622        params: ParamBufOwned,
623        intermediates: VTIntermediate,
624        final_byte: u8,
625    },
626    DcsData(Vec<u8>),
627    DcsEnd,
628    DcsCancel,
629    OscStart,
630    OscData(Vec<u8>),
631    OscEnd {
632        used_bel: bool,
633    },
634    OscCancel,
635}
636
637impl std::fmt::Debug for VTOwnedEvent {
638    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
639        self.borrow().fmt(f)
640    }
641}
642
643impl VTOwnedEvent {
644    pub fn borrow(&self) -> VTEvent<'_> {
645        match self {
646            VTOwnedEvent::Raw(s) => VTEvent::Raw(s),
647            VTOwnedEvent::C0(b) => VTEvent::C0(*b),
648            VTOwnedEvent::Esc {
649                intermediates,
650                final_byte,
651            } => VTEvent::Esc {
652                intermediates: intermediates.clone(),
653                final_byte: *final_byte,
654            },
655            VTOwnedEvent::Ss2 { char } => VTEvent::Ss2 { char: *char },
656            VTOwnedEvent::Ss3 { char } => VTEvent::Ss3 { char: *char },
657            VTOwnedEvent::Csi {
658                private,
659                params,
660                intermediates,
661                final_byte,
662            } => VTEvent::Csi {
663                private: private.clone(),
664                params: params.borrow(),
665                intermediates: intermediates.clone(),
666                final_byte: *final_byte,
667            },
668            VTOwnedEvent::DcsStart {
669                private,
670                params,
671                intermediates,
672                final_byte,
673            } => VTEvent::DcsStart {
674                private: private.clone(),
675                params: params.borrow(),
676                intermediates: intermediates.clone(),
677                final_byte: *final_byte,
678            },
679            VTOwnedEvent::DcsData(s) => VTEvent::DcsData(s),
680            VTOwnedEvent::DcsEnd => VTEvent::DcsEnd,
681            VTOwnedEvent::DcsCancel => VTEvent::DcsCancel,
682            VTOwnedEvent::OscStart => VTEvent::OscStart,
683            VTOwnedEvent::OscData(s) => VTEvent::OscData(s),
684            VTOwnedEvent::OscEnd { used_bel } => VTEvent::OscEnd {
685                used_bel: *used_bel,
686            },
687            VTOwnedEvent::OscCancel => VTEvent::OscCancel,
688        }
689    }
690}
691
692pub struct CSI<'a> {
693    pub private: Option<u8>,
694    pub params: ParamBuf<'a>,
695    pub intermediates: VTIntermediate,
696    pub final_byte: u8,
697}