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(&'a [u8]),
188 DcsCancel,
189
190 OscStart,
192 OscData(&'a [u8]),
193 OscEnd {
194 data: &'a [u8],
195 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 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}