sixel_tokenizer/
sixel_event.rs

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}