vt_push_parser/
event.rs

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