use std::error::Error;
use std::fmt;
use crate::kit::OCTANTS;
use crate::stage::Shader;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Glyphs(u8);
impl Glyphs {
pub const BASE: Self = Self(0);
pub const OCTANTS: Self = Self(1);
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
pub const fn contains(self, other: Self) -> bool {
other.0 & !self.0 == 0
}
const fn without(self, other: Self) -> Self {
Self(self.0 & !other.0)
}
pub fn octant(pixels: u8) -> char {
OCTANTS[usize::from(pixels)]
}
}
const REPERTOIRES: [(Glyphs, &str); 1] = [(Glyphs::OCTANTS, "octants")];
#[cfg(test)]
pub(crate) fn repertoire(glyph: char) -> Glyphs {
if ('\u{1cc00}'..='\u{1cebf}').contains(&glyph) || ('\u{1fb00}'..='\u{1fbff}').contains(&glyph)
{
Glyphs::OCTANTS
} else {
Glyphs::BASE
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Unfit {
missing: Glyphs,
}
impl Unfit {
pub fn missing(self) -> Glyphs {
self.missing
}
}
impl fmt::Display for Unfit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("the terminal lacks ")?;
let lacking = REPERTOIRES
.iter()
.filter(|(repertoire, _)| self.missing.contains(*repertoire));
for (i, (_, name)) in lacking.enumerate() {
if i > 0 {
f.write_str(", ")?;
}
f.write_str(name)?;
}
Ok(())
}
}
impl Error for Unfit {}
pub struct Recipe {
pub(crate) name: &'static str,
pub(crate) blurb: &'static str,
pub(crate) credit: &'static str,
pub(crate) needs: Glyphs,
pub(crate) summon: fn(u64) -> Box<dyn Shader>,
}
impl Recipe {
pub fn name(&self) -> &'static str {
self.name
}
pub fn blurb(&self) -> &'static str {
self.blurb
}
pub fn credit(&self) -> &'static str {
self.credit
}
pub fn needs(&self) -> Glyphs {
self.needs
}
pub fn fits(&self, glyphs: Glyphs) -> Result<(), Unfit> {
match self.needs.without(glyphs) {
Glyphs::BASE => Ok(()),
missing => Err(Unfit { missing }),
}
}
}
impl fmt::Debug for Recipe {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Recipe")
.field("name", &self.name)
.field("needs", &self.needs)
.finish_non_exhaustive()
}
}