1use 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
86pub 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))));