use core::fmt::Write;
use core::fmt::Display;
use core::ops::Range;
const UTF8_PRIVATE_USE_START: u32 = 0xE000;
pub(crate) const AGB_PRIVATE_USE_RANGE: Range<u32> =
UTF8_PRIVATE_USE_START..UTF8_PRIVATE_USE_START + 48;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct ChangeColour {
pub(crate) palette_index: u8,
}
impl ChangeColour {
const RANGE: Range<u32> = UTF8_PRIVATE_USE_START..UTF8_PRIVATE_USE_START + 16;
#[must_use]
pub const fn new(palette_index: u32) -> Self {
assert!(palette_index < 16, "paletted colour must be valid (0..=15)");
Self {
palette_index: palette_index as u8,
}
}
pub(crate) fn try_from_char(c: char) -> Option<Self> {
let c = u32::from(c);
if Self::RANGE.contains(&c) {
Some(Self::new(c - Self::RANGE.start))
} else {
None
}
}
#[must_use]
pub const fn to_char(self) -> char {
char::from_u32(self.palette_index as u32 + Self::RANGE.start).unwrap()
}
}
impl Display for ChangeColour {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_char(self.to_char())
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Tag(pub(crate) u8);
impl Tag {
const SET_RANGE: Range<u32> = UTF8_PRIVATE_USE_START + 16..UTF8_PRIVATE_USE_START + 32;
const UNSET_RANGE: Range<u32> = UTF8_PRIVATE_USE_START + 32..UTF8_PRIVATE_USE_START + 48;
#[must_use]
pub const fn new(tag: u32) -> Self {
assert!(tag < 16);
Self(tag as u8)
}
#[must_use]
pub const fn set(&self) -> char {
char::from_u32(self.0 as u32 + Self::SET_RANGE.start).unwrap()
}
#[must_use]
pub const fn unset(&self) -> char {
char::from_u32(self.0 as u32 + Self::UNSET_RANGE.start).unwrap()
}
pub(crate) fn new_set(c: char) -> Option<Self> {
let c = c as u32;
if Self::SET_RANGE.contains(&c) {
Some(Tag((c - Self::SET_RANGE.start) as u8))
} else {
None
}
}
pub(crate) fn new_unset(c: char) -> Option<Self> {
let c = c as u32;
if Self::UNSET_RANGE.contains(&c) {
Some(Tag((c - Self::UNSET_RANGE.start) as u8))
} else {
None
}
}
}