1use crate::platform_impl::PlatformIcon;
2use std::{error::Error, fmt, io, mem};
3
4#[repr(C)]
5#[derive(Debug)]
6pub(crate) struct Pixel {
7 pub(crate) r: u8,
8 pub(crate) g: u8,
9 pub(crate) b: u8,
10 pub(crate) a: u8,
11}
12
13pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>();
14
15#[derive(Debug)]
16pub enum BadIcon {
18 ByteCountNotDivisibleBy4 { byte_count: usize },
21 DimensionsVsPixelCount {
24 width: u32,
25 height: u32,
26 width_x_height: usize,
27 pixel_count: usize,
28 },
29 OsError(io::Error),
31}
32
33impl fmt::Display for BadIcon {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 BadIcon::ByteCountNotDivisibleBy4 { byte_count } => write!(f,
37 "The length of the `rgba` argument ({byte_count:?}) isn't divisible by 4, making it impossible to interpret as 32bpp RGBA pixels.",
38 ),
39 BadIcon::DimensionsVsPixelCount {
40 width,
41 height,
42 width_x_height,
43 pixel_count,
44 } => write!(f,
45 "The specified dimensions ({width:?}x{height:?}) don't match the number of pixels supplied by the `rgba` argument ({pixel_count:?}). For those dimensions, the expected pixel count is {width_x_height:?}.",
46 ),
47 BadIcon::OsError(e) => write!(f, "OS error when instantiating the icon: {e:?}"),
48 }
49 }
50}
51
52impl Error for BadIcon {
53 fn source(&self) -> Option<&(dyn Error + 'static)> {
54 Some(self)
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub(crate) struct RgbaIcon {
60 pub(crate) rgba: Vec<u8>,
61 pub(crate) width: u32,
62 pub(crate) height: u32,
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
67pub(crate) struct NoIcon;
68
69#[allow(dead_code)] mod constructors {
71 use super::*;
72
73 impl RgbaIcon {
74 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
75 if rgba.len() % PIXEL_SIZE != 0 {
76 return Err(BadIcon::ByteCountNotDivisibleBy4 {
77 byte_count: rgba.len(),
78 });
79 }
80 let pixel_count = rgba.len() / PIXEL_SIZE;
81 if pixel_count != (width * height) as usize {
82 Err(BadIcon::DimensionsVsPixelCount {
83 width,
84 height,
85 width_x_height: (width * height) as usize,
86 pixel_count,
87 })
88 } else {
89 Ok(RgbaIcon {
90 rgba,
91 width,
92 height,
93 })
94 }
95 }
96 }
97
98 impl NoIcon {
99 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
100 let _ = RgbaIcon::from_rgba(rgba, width, height)?;
102 Ok(NoIcon)
103 }
104 }
105}
106
107#[derive(Clone)]
109pub struct Icon {
110 pub(crate) inner: PlatformIcon,
111}
112
113impl fmt::Debug for Icon {
114 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
115 fmt::Debug::fmt(&self.inner, formatter)
116 }
117}
118
119impl Icon {
120 pub fn from_rgba(rgba: Vec<u8>, width: u32, height: u32) -> Result<Self, BadIcon> {
125 Ok(Icon {
126 inner: PlatformIcon::from_rgba(rgba, width, height)?,
127 })
128 }
129}