1use arrayvec::ArrayVec;
2use std::str;
3
4use crate::ParserError;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum SixelEvent {
8 ColorIntroducer {
9 color_number: u16,
10 color_coordinate_system: Option<ColorCoordinateSystem>,
11 },
12 RasterAttribute {
13 pan: usize,
14 pad: usize,
15 ph: Option<usize>,
16 pv: Option<usize>,
17 },
18 Data {
19 byte: u8,
20 },
21 Repeat {
22 repeat_count: usize,
23 byte_to_repeat: u8,
24 },
25 Dcs {
26 macro_parameter: Option<u8>,
27 transparent_background: Option<u8>,
28 horizontal_pixel_distance: Option<usize>,
29 },
30 GotoBeginningOfLine,
31 GotoNextLine,
32 UnknownSequence([Option<u8>; 5]),
33 End,
34}
35
36impl SixelEvent {
37 pub fn new_dcs(
38 macro_parameter: Option<u8>,
39 transparent_background: Option<u8>,
40 horizontal_pixel_distance: Option<usize>,
41 ) -> SixelEvent {
42 SixelEvent::Dcs {
43 macro_parameter,
44 transparent_background,
45 horizontal_pixel_distance,
46 }
47 }
48 pub fn new_color_introducer(
49 color_number: u16,
50 coordinate_system_indicator: Option<u8>,
51 x: Option<usize>,
52 y: Option<usize>,
53 z: Option<usize>,
54 ) -> Result<SixelEvent, ParserError> {
55 match (coordinate_system_indicator, x, y, z) {
56 (Some(coordinate_system_indicator), Some(x), Some(y), Some(z)) => {
57 let event = SixelEvent::ColorIntroducer {
58 color_number,
59 color_coordinate_system: Some(ColorCoordinateSystem::new(
60 coordinate_system_indicator,
61 x,
62 y,
63 z,
64 )?),
65 };
66 Ok(event)
67 }
68 (None, None, None, None) => {
69 let event = SixelEvent::ColorIntroducer {
70 color_number,
71 color_coordinate_system: None,
72 };
73 Ok(event)
74 }
75 _ => Err(ParserError::ParsingError),
76 }
77 }
78 pub fn color_introducer_from_fields(
79 pending_event_fields: &mut ArrayVec<ArrayVec<u8, 5>, 5>,
80 ) -> Result<SixelEvent, ParserError> {
81 let mut byte_fields = pending_event_fields.drain(..);
82 let color_number = mandatory_field_u16(byte_fields.next())?;
83 let coordinate_system_indicator = optional_field(byte_fields.next())?;
84 let x = optional_usize_field(byte_fields.next())?;
85 let y = optional_usize_field(byte_fields.next())?;
86 let z = optional_usize_field(byte_fields.next())?;
87 match (coordinate_system_indicator, x, y, z) {
88 (Some(coordinate_system_indicator), Some(x), Some(y), Some(z)) => {
89 let event = SixelEvent::ColorIntroducer {
90 color_number,
91 color_coordinate_system: Some(ColorCoordinateSystem::new(
92 coordinate_system_indicator,
93 x,
94 y,
95 z,
96 )?),
97 };
98 Ok(event)
99 }
100 (None, None, None, None) => {
101 let event = SixelEvent::ColorIntroducer {
102 color_number,
103 color_coordinate_system: None,
104 };
105 Ok(event)
106 }
107 _ => Err(ParserError::ParsingError),
108 }
109 }
110 pub fn new_raster(
111 pan: usize,
112 pad: usize,
113 ph: Option<usize>,
114 pv: Option<usize>,
115 ) -> Result<SixelEvent, ParserError> {
116 let event = SixelEvent::RasterAttribute { pan, pad, ph, pv };
117 Ok(event)
118 }
119 pub fn raster_attribute_from_fields(
120 pending_event_fields: &mut ArrayVec<ArrayVec<u8, 5>, 5>,
121 ) -> Result<SixelEvent, ParserError> {
122 let mut byte_fields = pending_event_fields.drain(..);
123 let pan = mandatory_usize_field(byte_fields.next())?;
124 let pad = mandatory_usize_field(byte_fields.next())?;
125 let ph = optional_usize_field(byte_fields.next())?;
126 let pv = optional_usize_field(byte_fields.next())?;
127 if byte_fields.next().is_some() {
128 return Err(ParserError::ParsingError);
129 }
130 let event = SixelEvent::RasterAttribute { pan, pad, ph, pv };
131 Ok(event)
132 }
133 pub fn dcs_from_fields(
134 pending_event_fields: &mut ArrayVec<ArrayVec<u8, 5>, 5>,
135 ) -> Result<SixelEvent, ParserError> {
136 let mut byte_fields = pending_event_fields.drain(..);
137 let macro_parameter = optional_field(byte_fields.next())?;
138 let transparent_background = optional_field(byte_fields.next())?;
139 let horizontal_pixel_distance = optional_usize_field(byte_fields.next())?;
140 if byte_fields.next().is_some() {
141 return Err(ParserError::ParsingError);
142 }
143 let event = SixelEvent::Dcs {
144 macro_parameter,
145 transparent_background,
146 horizontal_pixel_distance,
147 };
148 Ok(event)
149 }
150 pub fn new_repeat(repeat_count: usize, byte_to_repeat: u8) -> Result<SixelEvent, ParserError> {
151 let event = SixelEvent::Repeat {
152 repeat_count,
153 byte_to_repeat,
154 };
155 Ok(event)
156 }
157 pub fn repeat_from_fields(
158 pending_event_fields: &mut ArrayVec<ArrayVec<u8, 5>, 5>,
159 byte_to_repeat: u8,
160 ) -> Result<SixelEvent, ParserError> {
161 let mut byte_fields = pending_event_fields.drain(..);
162 let repeat_count = mandatory_usize_field(byte_fields.next())?;
163 if byte_fields.next().is_some() {
164 return Err(ParserError::ParsingError);
165 }
166 let event = SixelEvent::Repeat {
167 repeat_count: repeat_count.into(),
168 byte_to_repeat,
169 };
170 Ok(event)
171 }
172}
173
174#[derive(Clone, Copy, Debug, PartialEq, Eq)]
175pub enum ColorCoordinateSystem {
176 HLS(usize, usize, usize),
177 RGB(usize, usize, usize),
178}
179
180impl ColorCoordinateSystem {
181 pub fn new(
182 coordinate_system_indicator: u8,
183 x: usize,
184 y: usize,
185 z: usize,
186 ) -> Result<Self, ParserError> {
187 match coordinate_system_indicator {
188 1 => Ok(ColorCoordinateSystem::HLS(x, y, z)),
189 2 => Ok(ColorCoordinateSystem::RGB(x, y, z)),
190 _ => Err(ParserError::ParsingError),
191 }
192 }
193}
194
195fn bytes_to_u8(bytes: ArrayVec<u8, 5>) -> Result<u8, ParserError> {
196 Ok(u8::from_str_radix(str::from_utf8(&bytes)?, 10)?)
197}
198
199fn bytes_to_u16(bytes: ArrayVec<u8, 5>) -> Result<u16, ParserError> {
200 Ok(u16::from_str_radix(str::from_utf8(&bytes)?, 10)?)
201}
202
203fn bytes_to_usize(bytes: ArrayVec<u8, 5>) -> Result<usize, ParserError> {
204 Ok(usize::from_str_radix(str::from_utf8(&bytes)?, 10)?)
205}
206
207fn mandatory_field_u16(field: Option<ArrayVec<u8, 5>>) -> Result<u16, ParserError> {
208 bytes_to_u16(field.ok_or(ParserError::ParsingError)?)
209}
210
211fn mandatory_usize_field(field: Option<ArrayVec<u8, 5>>) -> Result<usize, ParserError> {
212 bytes_to_usize(field.ok_or(ParserError::ParsingError)?)
213}
214
215fn optional_field(field: Option<ArrayVec<u8, 5>>) -> Result<Option<u8>, ParserError> {
216 match field {
217 Some(field) => {
218 let parsed = bytes_to_u8(field)?;
219 Ok(Some(parsed))
220 }
221 None => Ok(None),
222 }
223}
224
225fn optional_usize_field(field: Option<ArrayVec<u8, 5>>) -> Result<Option<usize>, ParserError> {
226 match field {
227 Some(field) => {
228 let parsed = bytes_to_usize(field)?;
229 Ok(Some(parsed))
230 }
231 None => Ok(None),
232 }
233}