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