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 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 Raw(&'a [u8]),
146
147 C0(u8),
149
150 Esc {
152 intermediates: VTIntermediate,
153 final_byte: u8,
154 },
155
156 Csi {
158 private: Option<u8>,
159 params: ParamBuf<'a>,
160 intermediates: VTIntermediate,
161 final_byte: u8,
162 },
163
164 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 OscStart,
177 OscData(&'a [u8]),
178 OscEnd {
179 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 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}