1use std::io::{Cursor, Result, Write};
4
5use crate::serial::{ReadFrom, WriteTo};
6
7#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
12#[repr(transparent)]
13pub struct RgbColor(i32);
14
15impl RgbColor {
16 #[must_use]
18 pub const fn new(raw: i32) -> Self {
19 Self(raw)
20 }
21
22 #[must_use]
24 pub const fn raw(self) -> i32 {
25 self.0
26 }
27
28 #[must_use]
30 pub const fn red(self) -> u8 {
31 (self.0 as u32 >> 16) as u8
32 }
33
34 #[must_use]
36 pub const fn green(self) -> u8 {
37 (self.0 as u32 >> 8) as u8
38 }
39
40 #[must_use]
42 pub const fn blue(self) -> u8 {
43 self.0 as u8
44 }
45
46 #[must_use]
48 pub const fn with_alpha(self, alpha: u8) -> ArgbColor {
49 ArgbColor::new(((alpha as u32) << 24 | (self.0 as u32 & 0x00ff_ffff)) as i32)
50 }
51}
52
53impl WriteTo for RgbColor {
54 fn write(&self, writer: &mut impl Write) -> Result<()> {
55 self.0.write(writer)
56 }
57}
58
59impl ReadFrom for RgbColor {
60 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
61 Ok(Self::new(i32::read(data)?))
62 }
63}
64
65#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
67#[repr(transparent)]
68pub struct ArgbColor(i32);
69
70impl ArgbColor {
71 #[must_use]
73 pub const fn new(raw: i32) -> Self {
74 Self(raw)
75 }
76
77 #[must_use]
79 pub const fn raw(self) -> i32 {
80 self.0
81 }
82
83 #[must_use]
85 pub const fn alpha(self) -> u8 {
86 (self.0 as u32 >> 24) as u8
87 }
88
89 #[must_use]
91 pub const fn red(self) -> u8 {
92 (self.0 as u32 >> 16) as u8
93 }
94
95 #[must_use]
97 pub const fn green(self) -> u8 {
98 (self.0 as u32 >> 8) as u8
99 }
100
101 #[must_use]
103 pub const fn blue(self) -> u8 {
104 self.0 as u8
105 }
106
107 #[must_use]
109 pub const fn rgb(self) -> RgbColor {
110 RgbColor::new(self.0)
111 }
112}
113
114impl WriteTo for ArgbColor {
115 fn write(&self, writer: &mut impl Write) -> Result<()> {
116 self.0.write(writer)
117 }
118}
119
120impl ReadFrom for ArgbColor {
121 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
122 Ok(Self::new(i32::read(data)?))
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn rgb_preserves_ignored_upper_byte() {
132 let color = RgbColor::new(0x7f12_3456);
133
134 assert_eq!(color.raw(), 0x7f12_3456);
135 assert_eq!(
136 (color.red(), color.green(), color.blue()),
137 (0x12, 0x34, 0x56)
138 );
139 assert_eq!(color.with_alpha(0xaa).raw(), 0xaa12_3456_u32 as i32);
140 }
141
142 #[test]
143 fn argb_exposes_all_channels() {
144 let color = ArgbColor::new(0xaabb_ccdd_u32 as i32);
145
146 assert_eq!(
147 (color.alpha(), color.red(), color.green(), color.blue()),
148 (0xaa, 0xbb, 0xcc, 0xdd)
149 );
150 }
151}