use std::borrow::Cow;
use crate::render::Color;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Palette {
colors: Cow<'static, [Color]>,
}
impl Palette {
pub const OKABE_ITO: Palette = Palette::new(&[
Color::Rgb(230, 159, 0),
Color::Rgb(86, 180, 233),
Color::Rgb(0, 158, 115),
Color::Rgb(213, 94, 0),
Color::Rgb(204, 121, 167),
Color::Rgb(0, 114, 178),
Color::Rgb(240, 228, 66),
]);
pub const fn new(colors: &'static [Color]) -> Palette {
assert!(
!colors.is_empty(),
"Palette::new requires at least one color"
);
Palette {
colors: Cow::Borrowed(colors),
}
}
pub fn try_from_colors(colors: Vec<Color>) -> crate::Result<Palette> {
if colors.is_empty() {
return Err(crate::Error::EmptyDimension {
what: "Palette colors",
});
}
Ok(Palette {
colors: Cow::Owned(colors),
})
}
pub fn colors(&self) -> &[Color] {
&self.colors
}
pub(crate) fn validate(&self) -> crate::Result<()> {
if self.colors.is_empty() {
Err(crate::Error::EmptyDimension {
what: "Palette colors",
})
} else {
Ok(())
}
}
pub(crate) fn color(&self, index: usize) -> Color {
match self.colors.len() {
0 => Color::Default,
len => self.colors[index % len],
}
}
}
impl Default for Palette {
fn default() -> Palette {
Palette::OKABE_ITO
}
}
#[cfg(test)]
#[path = "tests/palette_tests.rs"]
mod tests;