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 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 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 Raw(&'a [u8]),
151
152 C0(u8),
154
155 Esc {
157 intermediates: VTIntermediate,
158 final_byte: u8,
159 },
160
161 Ss2 {
163 char: u8,
164 },
165
166 Ss3 {
168 char: u8,
169 },
170
171 Csi {
173 private: Option<u8>,
174 params: ParamBuf<'a>,
175 intermediates: VTIntermediate,
176 final_byte: u8,
177 },
178
179 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 OscStart,
192 OscData(&'a [u8]),
193 OscEnd {
194 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 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}