embedded_graphics/iterator/
raw.rs

1//! Raw data iterator.
2//!
3//! Raw data iterators are used to implement rendering of custom image formats. Most users
4//! won't need to use these types directly and should instead use [`ImageRaw`].
5//!
6//! The [`RawDataSlice`] is used to specify the raw data format for a byte slice. This slice can
7//! than be converted into an optimized iterator for that data format by using `into_iter()`.
8//!
9//! # Examples
10//!
11//! ```
12//! use embedded_graphics::{iterator::raw::RawDataSlice, pixelcolor::raw::{RawU16, BigEndian}};
13//!
14//! let data = [0xAA, 0xBB, 0x12, 0x34];
15//!
16//! // The data type and byte order needs to be specified explicitly to set the data format.
17//! let slice = RawDataSlice::<RawU16, BigEndian>::new(&data);
18//!
19//! let mut iter = slice.into_iter();
20//! assert_eq!(iter.next(), Some(RawU16::new(0xAABB)));
21//! assert_eq!(iter.next(), Some(RawU16::new(0x1234)));
22//! assert_eq!(iter.next(), None);
23//! ```
24//!
25//! [`ImageRaw`]: super::super::image::ImageRaw
26
27use core::{marker::PhantomData, slice};
28
29use byteorder::{ByteOrder, BE, LE};
30
31use crate::pixelcolor::raw::{
32    BigEndian, LittleEndian, RawData, RawU1, RawU16, RawU2, RawU24, RawU32, RawU4, RawU8,
33};
34
35/// Raw data slice.
36///
37/// This type is a wrapper around a byte array to specify the stored data format.
38///
39/// See the [module-level documentation] for more information.
40///
41/// [module-level documentation]: self
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
43#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
44pub struct RawDataSlice<'a, R, BO> {
45    data: &'a [u8],
46    raw_type: PhantomData<R>,
47    byte_order: PhantomData<BO>,
48}
49
50impl<'a, R, BO> RawDataSlice<'a, R, BO> {
51    /// Creates a new raw data slice.
52    pub const fn new(data: &'a [u8]) -> Self {
53        Self {
54            data,
55            raw_type: PhantomData,
56            byte_order: PhantomData,
57        }
58    }
59}
60
61macro_rules! impl_bits_iterator {
62    ($type:ident, $bit_index_bits:expr) => {
63        impl<'a, BO> IntoIterator for RawDataSlice<'a, $type, BO> {
64            type Item = $type;
65            type IntoIter = BitsIterator<'a, $type>;
66
67            fn into_iter(self) -> Self::IntoIter {
68                BitsIterator::new(self.data)
69            }
70        }
71
72        impl<'a> Iterator for BitsIterator<'a, $type> {
73            type Item = $type;
74
75            #[inline]
76            fn next(&mut self) -> Option<Self::Item> {
77                self.data.get(self.index >> $bit_index_bits).map(|byte| {
78                    // Number of bits the value needs to be shifted to the right for the first pixel.
79                    let first_pixel_shift = 8 - $type::BITS_PER_PIXEL;
80
81                    // Index to one of the pixels inside this byte.
82                    let sub_index = self.index & (1 << $bit_index_bits) - 1;
83
84                    // Number of bits the value needs to be shifted.
85                    let shift = first_pixel_shift - (sub_index << 3 - $bit_index_bits);
86
87                    self.index += 1;
88
89                    $type::new(*byte >> shift)
90                })
91            }
92
93            #[inline]
94            fn nth(&mut self, n: usize) -> Option<Self::Item> {
95                self.index = self.index.saturating_add(n);
96                self.next()
97            }
98
99            fn size_hint(&self) -> (usize, Option<usize>) {
100                let size =
101                    (self.data.len() * (8 / $type::BITS_PER_PIXEL)).saturating_sub(self.index);
102
103                (size, Some(size))
104            }
105        }
106    };
107}
108
109impl_bits_iterator!(RawU1, 3);
110impl_bits_iterator!(RawU2, 2);
111impl_bits_iterator!(RawU4, 1);
112
113impl<'a, BO> IntoIterator for RawDataSlice<'a, RawU8, BO> {
114    type Item = RawU8;
115    type IntoIter = ByteIterator<'a>;
116
117    fn into_iter(self) -> Self::IntoIter {
118        ByteIterator::new(self.data)
119    }
120}
121
122/// Iterator for raw data slices with less than 8 BPP.
123///
124/// See the [module-level documentation] for more information.
125///
126/// [module-level documentation]: self
127#[derive(Debug)]
128#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
129pub struct BitsIterator<'a, R> {
130    data: &'a [u8],
131    index: usize,
132    raw_type: PhantomData<R>,
133}
134
135impl<'a, R: RawData> BitsIterator<'a, R> {
136    const fn new(data: &'a [u8]) -> Self {
137        Self {
138            data,
139            index: 0,
140            raw_type: PhantomData,
141        }
142    }
143}
144
145/// Iterator for raw data slices with 8 BPP.
146///
147/// See the [module-level documentation] for more information.
148///
149/// [module-level documentation]: self
150#[derive(Debug)]
151#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
152pub struct ByteIterator<'a> {
153    data: slice::Iter<'a, u8>,
154}
155
156impl<'a> ByteIterator<'a> {
157    fn new(data: &'a [u8]) -> Self {
158        Self { data: data.iter() }
159    }
160}
161
162impl<'a> Iterator for ByteIterator<'a> {
163    type Item = RawU8;
164
165    #[inline]
166    fn next(&mut self) -> Option<Self::Item> {
167        self.data.next().copied().map(RawU8::new)
168    }
169
170    #[inline]
171    fn nth(&mut self, n: usize) -> Option<Self::Item> {
172        self.data.nth(n).copied().map(RawU8::new)
173    }
174
175    fn size_hint(&self) -> (usize, Option<usize>) {
176        self.data.size_hint()
177    }
178}
179
180/// Iterator for raw data slices more than 8 BPP.
181///
182/// See the [module-level documentation] for more information.
183///
184/// [module-level documentation]: self
185#[derive(Debug)]
186#[cfg_attr(feature = "defmt", derive(::defmt::Format))]
187pub struct BytesIterator<'a, R, BO> {
188    // MSRV: replace by ArrayChunks when the feature is stabilized
189    data: slice::ChunksExact<'a, u8>,
190    raw_type: PhantomData<R>,
191    byte_order: PhantomData<BO>,
192}
193
194impl<'a, R: RawData, BO> BytesIterator<'a, R, BO> {
195    fn new(data: &'a [u8]) -> Self {
196        Self {
197            data: data.chunks_exact(R::BITS_PER_PIXEL / 8),
198            raw_type: PhantomData,
199            byte_order: PhantomData,
200        }
201    }
202}
203
204macro_rules! impl_bytes_iterator {
205    ($type:ident, $byte_order:ident, $read_function:path) => {
206        impl<'a> Iterator for BytesIterator<'a, $type, $byte_order> {
207            type Item = $type;
208
209            #[inline]
210            fn next(&mut self) -> Option<Self::Item> {
211                self.data.next().map(|raw| $read_function(raw).into())
212            }
213
214            #[inline]
215            fn nth(&mut self, n: usize) -> Option<Self::Item> {
216                self.data.nth(n).map(|raw| $read_function(raw).into())
217            }
218
219            fn size_hint(&self) -> (usize, Option<usize>) {
220                self.data.size_hint()
221            }
222        }
223
224        impl<'a> IntoIterator for RawDataSlice<'a, $type, $byte_order> {
225            type Item = $type;
226            type IntoIter = BytesIterator<'a, $type, $byte_order>;
227
228            fn into_iter(self) -> Self::IntoIter {
229                BytesIterator::new(self.data)
230            }
231        }
232    };
233
234    ($type:ident, $read_function:ident) => {
235        impl_bytes_iterator!($type, LittleEndian, LE::$read_function);
236        impl_bytes_iterator!($type, BigEndian, BE::$read_function);
237    };
238}
239
240impl_bytes_iterator!(RawU16, read_u16);
241impl_bytes_iterator!(RawU24, read_u24);
242impl_bytes_iterator!(RawU32, read_u32);
243
244#[cfg(test)]
245mod tests {
246    use super::*;
247
248    const BITS_DATA: &[u8] = &[0x12, 0x48, 0x5A, 0x0F];
249    const BYTES_DATA_1: &[u8] = &[0x10, 0x20, 0x30, 0x40, 0x50, 0x60];
250    const BYTES_DATA_2: &[u8] = &[0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80];
251
252    #[test]
253    fn raw_u1() {
254        #[rustfmt::skip]
255        let expected = [
256            0, 0, 0, 1,
257            0, 0, 1, 0,
258            0, 1, 0, 0,
259            1, 0, 0, 0,
260            0, 1, 0, 1,
261            1, 0, 1, 0,
262            0, 0, 0, 0,
263            1, 1, 1, 1,
264        ]
265        .iter()
266        .copied()
267        .map(RawU1::new);
268
269        let iter = RawDataSlice::<RawU1, LittleEndian>::new(BITS_DATA).into_iter();
270        assert!(iter.eq(expected));
271    }
272
273    #[test]
274    fn raw_u2() {
275        let expected = [0, 1, 0, 2, 1, 0, 2, 0, 1, 1, 2, 2, 0, 0, 3, 3]
276            .iter()
277            .copied()
278            .map(RawU2::new);
279
280        let iter = RawDataSlice::<RawU2, LittleEndian>::new(BITS_DATA).into_iter();
281        assert!(iter.eq(expected));
282    }
283
284    #[test]
285    fn raw_u4() {
286        let expected = [0x1, 0x2, 0x4, 0x8, 0x5, 0xA, 0x0, 0xF]
287            .iter()
288            .copied()
289            .map(RawU4::new);
290
291        let iter = RawDataSlice::<RawU4, LittleEndian>::new(BITS_DATA).into_iter();
292        assert!(iter.eq(expected));
293    }
294
295    #[test]
296    fn raw_u8() {
297        let expected = BYTES_DATA_1.iter().map(|&v| RawU8::new(v));
298
299        let iter = RawDataSlice::<RawU8, LittleEndian>::new(BYTES_DATA_1).into_iter();
300        assert!(iter.eq(expected));
301    }
302
303    #[test]
304    fn raw_u16_le() {
305        let expected = [0x2010, 0x4030, 0x6050].iter().copied().map(RawU16::new);
306
307        let iter = RawDataSlice::<RawU16, LittleEndian>::new(BYTES_DATA_1).into_iter();
308        assert!(iter.eq(expected));
309    }
310
311    #[test]
312    fn raw_u16_be() {
313        let expected = [0x1020, 0x3040, 0x5060].iter().copied().map(RawU16::new);
314
315        let iter = RawDataSlice::<RawU16, BigEndian>::new(BYTES_DATA_1).into_iter();
316        assert!(iter.eq(expected));
317    }
318
319    #[test]
320    fn raw_u16_excess_bytes_are_ignored() {
321        let iter = RawDataSlice::<RawU16, LittleEndian>::new(&[0; 3]).into_iter();
322        assert_eq!(iter.count(), 1);
323    }
324
325    #[test]
326    fn raw_u24_le() {
327        let expected = [0x302010, 0x605040].iter().copied().map(RawU24::new);
328
329        let iter = RawDataSlice::<RawU24, LittleEndian>::new(BYTES_DATA_1).into_iter();
330        assert!(iter.into_iter().eq(expected));
331    }
332
333    #[test]
334    fn raw_u24_be() {
335        let expected = [0x102030, 0x405060].iter().copied().map(RawU24::new);
336
337        let iter = RawDataSlice::<RawU24, BigEndian>::new(BYTES_DATA_1).into_iter();
338        assert!(iter.into_iter().eq(expected));
339    }
340
341    #[test]
342    fn raw_u24_excess_bytes_are_ignored() {
343        let iter = RawDataSlice::<RawU24, LittleEndian>::new(&[0; 7]).into_iter();
344        assert_eq!(iter.count(), 2);
345    }
346
347    #[test]
348    fn raw_u32_le() {
349        let expected = [0x40302010, 0x80706050].iter().copied().map(RawU32::new);
350
351        let iter = RawDataSlice::<RawU32, LittleEndian>::new(BYTES_DATA_2).into_iter();
352        assert!(iter.into_iter().eq(expected));
353    }
354
355    #[test]
356    fn raw_u32_be() {
357        let expected = [0x10203040, 0x50607080].iter().copied().map(RawU32::new);
358
359        let iter = RawDataSlice::<RawU32, BigEndian>::new(BYTES_DATA_2).into_iter();
360        assert!(iter.into_iter().eq(expected));
361    }
362
363    #[test]
364    fn raw_u32_excess_bytes_are_ignored() {
365        let iter = RawDataSlice::<RawU32, LittleEndian>::new(&[0; 13]).into_iter();
366        assert_eq!(iter.count(), 3);
367    }
368}