1 use crate::code::AnsiCode;
2 use crate::error::Error;
3 use std::{convert::TryInto, slice::Iter};
4 use tui::style::{Color, Modifier, Style};
5 
6 #[derive(Debug)]
7 pub struct Stack<T> {
8     st: Vec<T>,
9     lock: bool,
10 }
11 
12 impl<T> Stack<T> {
new() -> Self13     pub fn new() -> Self {
14         Self {
15             st: Vec::<T>::new(),
16             lock: true,
17         }
18     }
push(&mut self, value: T)19     pub fn push(&mut self, value: T) {
20         self.st.push(value);
21     }
pop(&mut self) -> Option<T>22     pub fn pop(&mut self) -> Option<T> {
23         self.st.pop()
24     }
first(&self) -> Option<&T>25     pub fn first(&self) -> Option<&T> {
26         self.st.first()
27     }
last(&self) -> Option<&T>28     pub fn last(&self) -> Option<&T> {
29         self.st.last()
30     }
iter(&mut self) -> Iter<T>31     pub fn iter(&mut self) -> Iter<T> {
32         self.st.iter()
33     }
len(&mut self) -> usize34     pub fn len(&mut self) -> usize {
35         self.st.len()
36     }
37     // pub fn append(&mut self, other: &mut Vec<T>) {
38     //     self.st.append(other)
39     // }
clear(&mut self)40     pub fn clear(&mut self) {
41         self.st.clear();
42     }
lock(&mut self)43     pub fn lock(&mut self) {
44         self.st.clear();
45         self.lock = true
46     }
unlock(&mut self)47     pub fn unlock(&mut self) {
48         self.st.clear();
49         self.lock = false
50     }
51     // pub fn is_locked(&self) -> bool {
52     //     self.lock
53     // }
is_empty(&self) -> bool54     pub fn is_empty(&self) -> bool {
55         self.st.is_empty()
56     }
is_unlocked(&self) -> bool57     pub fn is_unlocked(&self) -> bool {
58         !self.lock
59     }
60 }
61 
62 impl Stack<u8> {
parse_usize(&mut self) -> Result<usize, Error>63     pub fn parse_usize(&mut self) -> Result<usize, Error> {
64         if self.is_empty() {
65             return Err(Error::UsizeParsingError);
66         }
67         let mut num: usize = 0;
68         for n in self.iter() {
69             // num = num * 10 + (n.saturating_sub(48_u8)) as usize
70             num = num * 10 + (n - 48_u8) as usize
71         }
72         self.clear();
73         Ok(num)
74     }
parse_color(&mut self) -> Result<Color, Error>75     pub fn parse_color(&mut self) -> Result<Color, Error> {
76         let color: Color;
77         let length = self.len();
78         match length {
79             2 => color = Color::Indexed(self.pop().expect("Shouldn't happen len check in place")),
80             4 => {
81                 let b = self.pop().expect("Shouldn't happen len check in place");
82                 let g = self.pop().expect("Shouldn't happen len check in place");
83                 let r = self.pop().expect("Shouldn't happen len check in place");
84                 color = Color::Rgb(r, g, b);
85             }
86             _ => {
87                 return Err(Error::ColorParsingError);
88             }
89         }
90         self.clear();
91         Ok(color)
92     }
93 }
94 
95 #[derive(Debug, PartialEq, Clone, Copy)]
96 #[repr(u8)]
97 pub enum ColorLayer {
98     Background,
99     Foreground,
100 }
101 
102 #[derive(Debug)]
103 pub struct AnsiGraphicsStack {
104     stack: Vec<usize>,
105     lock: bool,
106 }
107 
108 impl AnsiGraphicsStack {
new() -> Self109     pub fn new() -> Self {
110         Self {
111             stack: Vec::new(),
112             lock: true,
113         }
114     }
push(&mut self, sequence: usize)115     pub fn push(&mut self, sequence: usize) {
116         self.stack.push(sequence);
117     }
iter(&mut self) -> Iter<usize>118     pub fn iter(&mut self) -> Iter<usize> {
119         self.stack.iter()
120     }
lock(&mut self)121     pub fn lock(&mut self) {
122         self.stack.clear();
123         self.lock = true;
124     }
unlock(&mut self)125     pub fn unlock(&mut self) {
126         self.stack.clear();
127         self.lock = false;
128     }
is_locked(&self) -> bool129     pub fn is_locked(&self) -> bool {
130         self.lock
131     }
is_unlocked(&self) -> bool132     pub fn is_unlocked(&self) -> bool {
133         !self.lock
134     }
135 
136     // pub fn len(&self) -> usize {
137     //     self.stack.len()
138     // }
139 
parse_ansi(&mut self) -> Result<Style, Error>140     pub fn parse_ansi(&mut self) -> Result<Style, Error> {
141         let mut style = Style::default();
142 
143         // let mut stack: Stack<u8> = Stack::new();
144         let mut color_stack: Stack<u8> = Stack::new();
145 
146         let mut layer: Option<ColorLayer> = None;
147 
148         for sequence in self.iter().copied() {
149             // sequence should always be an u8
150             // but since you can actually write more than u8 (incase of erroneous input)
151             // i'm using usize
152             // if input is greater than u8 simply skip the iteration and clear the color_stack.
153 
154             let code;
155             let _seq: Result<u8, _> = sequence.try_into();
156 
157             let sequence: u8;
158             if let Ok(_s) = _seq {
159                 sequence = _s;
160                 code = AnsiCode::from(_s);
161             } else {
162                 // More than a u8
163                 color_stack.lock();
164                 continue;
165             }
166 
167             if color_stack.is_unlocked() {
168                 // don't match against other stuff
169                 // on first run it will push 2/5 ie rgb or indexed color
170                 if color_stack.is_empty() {
171                     // sequence should be either 2 or 5
172                     color_stack.push(sequence);
173                     continue;
174                 }
175                 match color_stack.first().ok_or(Error::StackEmpty)? {
176                     2 => {
177                         // first number is 2 ,second, third and fourth are r, g, b
178                         if color_stack.len() <= 4 {
179                             color_stack.push(sequence);
180                         }
181                         if color_stack.len() == 4 {
182                             match layer.ok_or(Error::UnknownLayer)? {
183                                 ColorLayer::Foreground => {
184                                     style = style.fg(color_stack.parse_color()?);
185                                 }
186                                 ColorLayer::Background => {
187                                     style = style.bg(color_stack.parse_color()?);
188                                 }
189                             }
190                         }
191                     }
192                     5 => {
193                         if color_stack.len() <= 2 {
194                             // first number is  5 second is the color index
195                             color_stack.push(sequence);
196                         }
197                         if color_stack.len() == 2 {
198                             match layer.ok_or(Error::UnknownLayer)? {
199                                 ColorLayer::Foreground => {
200                                     style = style.fg(color_stack.parse_color()?);
201                                 }
202                                 ColorLayer::Background => {
203                                     style = style.bg(color_stack.parse_color()?);
204                                 }
205                             }
206                         }
207                     }
208                     _ => {
209                         color_stack.lock();
210                     } // first number is not 2 or 5 lock
211                 }
212                 //
213                 continue;
214             }
215             match code {
216                 AnsiCode::Reset => style = Style::default(),
217                 AnsiCode::Bold => style = style.add_modifier(Modifier::BOLD),
218                 AnsiCode::Faint => style = style.add_modifier(Modifier::DIM),
219                 AnsiCode::Italic => style = style.add_modifier(Modifier::ITALIC),
220                 AnsiCode::Underline => style = style.add_modifier(Modifier::UNDERLINED),
221                 AnsiCode::SlowBlink => style = style.add_modifier(Modifier::SLOW_BLINK),
222                 AnsiCode::RapidBlink => style = style.add_modifier(Modifier::RAPID_BLINK),
223                 AnsiCode::Reverse => style = style.add_modifier(Modifier::REVERSED),
224                 AnsiCode::Conceal => style = style.add_modifier(Modifier::HIDDEN),
225                 AnsiCode::CrossedOut => style = style.add_modifier(Modifier::CROSSED_OUT),
226                 AnsiCode::DefaultForegroundColor => style = style.fg(Color::Reset),
227                 AnsiCode::DefaultBackgroundColor => style = style.bg(Color::Reset),
228                 AnsiCode::SetForegroundColor => {
229                     // color_layer = Some(ColorLayer::Foreground)
230                     // current byte is 38
231                     layer = Some(ColorLayer::Foreground);
232                     color_stack.unlock();
233                 }
234                 AnsiCode::SetBackgroundColor => {
235                     // color_layer = Some(ColorLayer::Background)
236                     // current byte is 48
237                     layer = Some(ColorLayer::Background);
238                     color_stack.unlock();
239                 }
240                 AnsiCode::ForegroundColor(color) => style = style.fg(color),
241                 AnsiCode::BackgroundColor(color) => style = style.bg(color),
242                 _ => (),
243             }
244         }
245 
246         Ok(style)
247     }
248 }
249