1use crate::Size;
3
4use std::mem;
5
6pub fn from_rgba(
8 rgba: Vec<u8>,
9 width: u32,
10 height: u32,
11) -> Result<Icon, Error> {
12 const PIXEL_SIZE: usize = mem::size_of::<u8>() * 4;
13
14 if rgba.len() % PIXEL_SIZE != 0 {
15 return Err(Error::ByteCountNotDivisibleBy4 {
16 byte_count: rgba.len(),
17 });
18 }
19
20 let pixel_count = rgba.len() / PIXEL_SIZE;
21
22 if pixel_count != (width * height) as usize {
23 return Err(Error::DimensionsVsPixelCount {
24 width,
25 height,
26 width_x_height: (width * height) as usize,
27 pixel_count,
28 });
29 }
30
31 Ok(Icon {
32 rgba,
33 size: Size::new(width, height),
34 })
35}
36
37#[derive(Debug, Clone)]
39pub struct Icon {
40 rgba: Vec<u8>,
41 size: Size<u32>,
42}
43
44impl Icon {
45 pub fn into_raw(self) -> (Vec<u8>, Size<u32>) {
47 (self.rgba, self.size)
48 }
49}
50
51#[derive(Debug, thiserror::Error)]
52pub enum Error {
54 #[error(
57 "The provided RGBA data (with length {byte_count}) isn't divisible \
58 by 4. Therefore, it cannot be safely interpreted as 32bpp RGBA pixels"
59 )]
60 ByteCountNotDivisibleBy4 {
61 byte_count: usize,
63 },
64 #[error(
67 "The number of RGBA pixels ({pixel_count}) does not match the \
68 provided dimensions ({width}x{height})."
69 )]
70 DimensionsVsPixelCount {
71 width: u32,
73 height: u32,
75 width_x_height: usize,
77 pixel_count: usize,
79 },
80}