anstyle_parse/state/
definitions.rs

1use core::mem;
2
3#[derive(Debug, Copy, Clone, PartialEq, Eq)]
4#[repr(u8)]
5pub enum State {
6    Anywhere = 0,
7    CsiEntry = 1,
8    CsiIgnore = 2,
9    CsiIntermediate = 3,
10    CsiParam = 4,
11    DcsEntry = 5,
12    DcsIgnore = 6,
13    DcsIntermediate = 7,
14    DcsParam = 8,
15    DcsPassthrough = 9,
16    Escape = 10,
17    EscapeIntermediate = 11,
18    Ground = 12,
19    OscString = 13,
20    SosPmApcString = 14,
21    Utf8 = 15,
22}
23
24impl Default for State {
25    #[inline]
26    fn default() -> State {
27        State::Ground
28    }
29}
30
31impl TryFrom<u8> for State {
32    type Error = u8;
33
34    #[inline(always)]
35    fn try_from(raw: u8) -> Result<Self, Self::Error> {
36        STATES.get(raw as usize).ok_or(raw).copied()
37    }
38}
39
40const STATES: [State; 16] = [
41    State::Anywhere,
42    State::CsiEntry,
43    State::CsiIgnore,
44    State::CsiIntermediate,
45    State::CsiParam,
46    State::DcsEntry,
47    State::DcsIgnore,
48    State::DcsIntermediate,
49    State::DcsParam,
50    State::DcsPassthrough,
51    State::Escape,
52    State::EscapeIntermediate,
53    State::Ground,
54    State::OscString,
55    State::SosPmApcString,
56    State::Utf8,
57];
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60#[repr(u8)]
61pub enum Action {
62    Nop = 0,
63    Clear = 1,
64    Collect = 2,
65    CsiDispatch = 3,
66    EscDispatch = 4,
67    Execute = 5,
68    Hook = 6,
69    Ignore = 7,
70    OscEnd = 8,
71    OscPut = 9,
72    OscStart = 10,
73    Param = 11,
74    Print = 12,
75    Put = 13,
76    Unhook = 14,
77    BeginUtf8 = 15,
78}
79
80impl Default for Action {
81    #[inline]
82    fn default() -> Action {
83        Action::Nop
84    }
85}
86
87impl TryFrom<u8> for Action {
88    type Error = u8;
89
90    #[inline(always)]
91    fn try_from(raw: u8) -> Result<Self, Self::Error> {
92        ACTIONS.get(raw as usize).ok_or(raw).copied()
93    }
94}
95
96const ACTIONS: [Action; 16] = [
97    Action::Nop,
98    Action::Clear,
99    Action::Collect,
100    Action::CsiDispatch,
101    Action::EscDispatch,
102    Action::Execute,
103    Action::Hook,
104    Action::Ignore,
105    Action::OscEnd,
106    Action::OscPut,
107    Action::OscStart,
108    Action::Param,
109    Action::Print,
110    Action::Put,
111    Action::Unhook,
112    Action::BeginUtf8,
113];
114
115/// Unpack a u8 into a State and Action
116///
117/// The implementation of this assumes that there are *precisely* 16 variants for both Action and
118/// State. Furthermore, it assumes that the enums are tag-only; that is, there is no data in any
119/// variant.
120///
121/// Bad things will happen if those invariants are violated.
122#[inline(always)]
123pub const fn unpack(delta: u8) -> (State, Action) {
124    unsafe {
125        (
126            // State is stored in bottom 4 bits
127            mem::transmute(delta & 0x0f),
128            // Action is stored in top 4 bits
129            mem::transmute(delta >> 4),
130        )
131    }
132}
133
134#[inline(always)]
135#[cfg(test)]
136pub const fn pack(state: State, action: Action) -> u8 {
137    (action as u8) << 4 | state as u8
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn unpack_state_action() {
146        match unpack(0xee) {
147            (State::SosPmApcString, Action::Unhook) => (),
148            _ => panic!("unpack failed"),
149        }
150
151        match unpack(0x0f) {
152            (State::Utf8, Action::Nop) => (),
153            _ => panic!("unpack failed"),
154        }
155
156        match unpack(0xff) {
157            (State::Utf8, Action::BeginUtf8) => (),
158            _ => panic!("unpack failed"),
159        }
160    }
161
162    #[test]
163    fn pack_state_action() {
164        match unpack(0xee) {
165            (State::SosPmApcString, Action::Unhook) => (),
166            _ => panic!("unpack failed"),
167        }
168
169        match unpack(0x0f) {
170            (State::Utf8, Action::Nop) => (),
171            _ => panic!("unpack failed"),
172        }
173
174        match unpack(0xff) {
175            (State::Utf8, Action::BeginUtf8) => (),
176            _ => panic!("unpack failed"),
177        }
178    }
179}