control_code/
control.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use std::io::{self, Write};
16use smallvec::SmallVec;
17use nom::{self, IResult, Needed};
18
19use {Format, C0, C1, DEC, CSI, SGR};
20
21#[derive(Eq, PartialEq, Clone, Debug)]
22pub enum Control {
23	C0(C0::T),
24	C1(C1::T),
25	DEC(DEC::T),
26}
27
28impl From<C0::T> for Control {
29	#[inline]
30	fn from(value: C0::T) -> Control {
31		Control::C0(value)
32	}
33}
34
35impl From<C1::T> for Control {
36	#[inline]
37	fn from(value: C1::T) -> Control {
38		Control::C1(value)
39	}
40}
41
42impl From<DEC::T> for Control {
43	#[inline]
44	fn from(value: DEC::T) -> Control {
45		Control::DEC(value)
46	}
47}
48
49impl From<CSI::T> for Control {
50	#[inline]
51	fn from(value: CSI::T) -> Control {
52		Control::C1(C1::ControlSequence(value))
53	}
54}
55
56impl From<SGR::T> for Control {
57	#[inline]
58	fn from(value: SGR::T) -> Control {
59		Control::C1(C1::ControlSequence(CSI::SelectGraphicalRendition(small_vec![value])))
60	}
61}
62
63impl From<SmallVec<[SGR::T; CSI::SIZE]>> for Control {
64	#[inline]
65	fn from(value: SmallVec<[SGR::T; CSI::SIZE]>) -> Control {
66		Control::C1(C1::ControlSequence(CSI::SelectGraphicalRendition(value)))
67	}
68}
69
70impl Format for Control {
71	#[inline]
72	fn fmt<W: Write>(&self, f: W) -> io::Result<()> {
73		match self {
74			&Control::C0(ref value) =>
75				value.fmt(f),
76
77			&Control::C1(ref value) =>
78				value.fmt(f),
79
80			&Control::DEC(ref value) =>
81				value.fmt(f),
82		}
83	}
84}
85
86/// Parse a control code.
87pub fn parse(i: &[u8]) -> IResult<&[u8], Control> {
88	const TABLE: [u8; 256] = [
89		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
90		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
91		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
98		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
99		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105	];
106
107	if i.is_empty() {
108		return IResult::Incomplete(Needed::Unknown);
109	}
110
111	if TABLE[i[0] as usize] == 0 {
112		return IResult::Error(nom::ErrorKind::Custom(0));
113	}
114
115	control(i)
116}
117
118named!(control<Control>,
119	alt!(
120		map!(DEC::parse, |c| Control::DEC(c))
121		|
122		map!(C1::parse, |c| match c {
123			C1::ControlSequence(CSI::Unknown(id, modifier, args)) => {
124				if let Some(c) = DEC::CSI::normal(id, modifier, &args) {
125					Control::DEC(c)
126				}
127				else {
128					Control::C1(C1::ControlSequence(CSI::Unknown(id, modifier, args)))
129				}
130			}
131
132			C1::ControlSequence(CSI::Private(id, modifier, args)) => {
133				if let Some(c) = DEC::CSI::private(id, modifier, &args) {
134					Control::DEC(c)
135				}
136				else {
137					Control::C1(C1::ControlSequence(CSI::Private(id, modifier, args)))
138				}
139			}
140
141			control =>
142				Control::C1(control)
143		})
144		|
145		map!(C0::parse,  |c| Control::C0(c))));