playdate_color/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![feature(const_trait_impl)]
3#![feature(impl_trait_in_assoc_type)]
4
5extern crate sys;
6use core::ptr::NonNull;
7use core::usize;
8
9use sys::error::NullPtrError;
10use sys::ffi::LCDColor;
11use sys::ffi::LCDPattern;
12use sys::ffi::LCDSolidColor;
13
14
15#[derive(PartialEq, Clone)]
16#[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
17pub enum Color<'t> {
18	Solid(LCDSolidColor),
19	Pattern(&'t LCDPattern),
20}
21
22impl Color<'_> {
23	pub const WHITE: Self = Self::Solid(LCDSolidColor::kColorWhite);
24	pub const BLACK: Self = Self::Solid(LCDSolidColor::kColorBlack);
25	pub const CLEAR: Self = Self::Solid(LCDSolidColor::kColorClear);
26	pub const XOR: Self = Self::Solid(LCDSolidColor::kColorXOR);
27}
28
29impl<'t> From<Color<'t>> for LCDColor
30	where Self: 't,
31	      LCDColor: 't
32{
33	fn from(color: Color) -> Self {
34		match color {
35			Color::Solid(color) => color as LCDColor,
36			Color::Pattern(pattern) => (pattern as *const u8) as LCDColor,
37		}
38	}
39}
40
41impl<'t> TryFrom<LCDColor> for Color<'t>
42	where LCDColor: 't,
43	      Self: 't
44{
45	type Error = NullPtrError;
46
47	fn try_from(color: LCDColor) -> Result<Self, Self::Error> {
48		match color {
49			0 => Ok(Self::Solid(LCDSolidColor::BLACK)),
50			1 => Ok(Self::Solid(LCDSolidColor::WHITE)),
51			2 => Ok(Self::Solid(LCDSolidColor::CLEAR)),
52			3 => Ok(Self::Solid(<LCDSolidColor as LCDColorConst>::XOR)),
53			color => {
54				NonNull::new(color as *mut LCDPattern).ok_or(NullPtrError)
55				                                      .map(|nn| Self::Pattern(unsafe { nn.as_ref() }))
56			},
57		}
58	}
59}
60
61impl<'t> From<&'t LCDPattern> for Color<'t> {
62	fn from(pattern: &'t LCDPattern) -> Self { Color::Pattern(pattern) }
63}
64
65
66// TODO: LCDColorExt should be const_trait
67#[deprecated = "Useless until const_trait is experimental and incomplete. Use LCDColorConst instead."]
68pub trait LCDColorExt {
69	#![allow(non_snake_case)]
70	fn White() -> Self;
71	fn Black() -> Self;
72	fn Clear() -> Self;
73	fn XOR() -> Self;
74}
75
76#[allow(deprecated)]
77impl LCDColorExt for LCDColor {
78	#![allow(non_snake_case)]
79	fn White() -> Self { LCDSolidColor::kColorWhite as Self }
80	fn Black() -> Self { LCDSolidColor::kColorBlack as Self }
81	fn Clear() -> Self { LCDSolidColor::kColorClear as Self }
82	fn XOR() -> Self { LCDSolidColor::kColorXOR as Self }
83}
84
85#[allow(deprecated)]
86impl LCDColorExt for LCDSolidColor {
87	#![allow(non_snake_case)]
88	fn White() -> Self { LCDSolidColor::kColorWhite }
89	fn Black() -> Self { LCDSolidColor::kColorBlack }
90	fn Clear() -> Self { LCDSolidColor::kColorClear }
91	fn XOR() -> Self { LCDSolidColor::kColorXOR }
92}
93
94pub trait LCDColorConst {
95	const WHITE: Self;
96	const BLACK: Self;
97	const CLEAR: Self;
98	const XOR: Self;
99}
100
101impl LCDColorConst for LCDColor {
102	const WHITE: Self = LCDSolidColor::kColorWhite as Self;
103	const BLACK: Self = LCDSolidColor::kColorBlack as Self;
104	const CLEAR: Self = LCDSolidColor::kColorClear as Self;
105	const XOR: Self = LCDSolidColor::kColorXOR as Self;
106}
107
108impl LCDColorConst for LCDSolidColor {
109	const WHITE: Self = LCDSolidColor::kColorWhite as Self;
110	const BLACK: Self = LCDSolidColor::kColorBlack as Self;
111	const CLEAR: Self = LCDSolidColor::kColorClear as Self;
112	const XOR: Self = LCDSolidColor::kColorXOR as Self;
113}
114
115
116// TODO: LCDColorIs should be const_trait
117pub trait LCDColorIs {
118	fn is_solid(&self) -> bool;
119	fn is_pattern(&self) -> bool;
120}
121
122impl LCDColorIs for LCDColor {
123	fn is_solid(&self) -> bool {
124		let color = *self as usize;
125		color >= LCDSolidColor::kColorBlack as _ && color <= LCDSolidColor::kColorXOR as _
126	}
127	fn is_pattern(&self) -> bool { !self.is_solid() }
128}
129
130
131// TODO: IntoLCDColor should be const_trait
132pub trait IntoLCDColor {
133	fn into_color(self) -> LCDColor;
134}
135
136impl IntoLCDColor for LCDSolidColor {
137	fn into_color(self) -> LCDColor { self as LCDColor }
138}
139
140impl<'t> IntoLCDColor for &'t LCDPattern where LCDColor: 't {
141	#[inline(always)]
142	fn into_color(self) -> LCDColor { self as *const u8 as _ }
143}
144
145
146// TODO: LCDColorFmt should be const_trait
147pub trait LCDColorFmt<'t> {
148	type Display: 't + core::fmt::Debug + core::fmt::Display;
149	fn display(&'t self) -> Self::Display;
150}
151
152impl<'t> LCDColorFmt<'t> for LCDSolidColor {
153	type Display = LCDColorDisplay<'t, Self>;
154	fn display(&self) -> LCDColorDisplay<'_, Self> { LCDColorDisplay(self) }
155}
156
157pub struct LCDColorDisplay<'t, T>(&'t T);
158
159impl core::fmt::Debug for LCDColorDisplay<'_, LCDSolidColor> {
160	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
161		f.write_str("Solid")?;
162		let name = match self.0 {
163			LCDSolidColor::kColorBlack => "Black",
164			LCDSolidColor::kColorWhite => "White",
165			LCDSolidColor::kColorClear => "Clear",
166			LCDSolidColor::kColorXOR => "XOR",
167		};
168		f.write_str(name)
169	}
170}
171
172impl core::fmt::Display for LCDColorDisplay<'_, LCDSolidColor> {
173	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174		let ch = match self.0 {
175			LCDSolidColor::kColorBlack => 'B',
176			LCDSolidColor::kColorWhite => 'W',
177			LCDSolidColor::kColorClear => 'C',
178			LCDSolidColor::kColorXOR => 'X',
179		};
180		write!(f, "{ch}")
181	}
182}
183
184impl core::fmt::Debug for LCDColorDisplay<'_, LCDColor> {
185	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
186		match self.0 {
187			n if *n == LCDSolidColor::kColorBlack as _ => LCDSolidColor::kColorBlack.display().fmt(f),
188			n if *n == LCDSolidColor::kColorWhite as _ => LCDSolidColor::kColorWhite.display().fmt(f),
189			n if *n == LCDSolidColor::kColorClear as _ => LCDSolidColor::kColorClear.display().fmt(f),
190			n if *n == LCDSolidColor::kColorXOR as _ => LCDSolidColor::kColorXOR.display().fmt(f),
191			p => write!(f, "Pattern({:p})", *p as *const u8),
192		}
193	}
194}
195
196impl core::fmt::Display for LCDColorDisplay<'_, LCDColor> {
197	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
198		match self.0 {
199			n if *n == LCDSolidColor::kColorBlack as _ => LCDSolidColor::kColorBlack.display().fmt(f),
200			n if *n == LCDSolidColor::kColorWhite as _ => LCDSolidColor::kColorWhite.display().fmt(f),
201			n if *n == LCDSolidColor::kColorClear as _ => LCDSolidColor::kColorClear.display().fmt(f),
202			n if *n == LCDSolidColor::kColorXOR as _ => LCDSolidColor::kColorXOR.display().fmt(f),
203			_ => write!(f, "Pattern"),
204		}
205	}
206}