#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
}
impl Color {
pub const fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
}
#[derive(Debug, Clone)]
pub struct ColorPalette {
colors: Vec<Color>,
}
impl ColorPalette {
pub fn new(colors: Vec<Color>) -> Self {
assert!(
!colors.is_empty(),
"a color palette needs at least one color"
);
Self { colors }
}
pub fn by_class_id(&self, class_id: usize) -> Color {
self.colors[class_id % self.colors.len()]
}
pub fn len(&self) -> usize {
self.colors.len()
}
pub fn is_empty(&self) -> bool {
self.colors.is_empty()
}
}
impl Default for ColorPalette {
fn default() -> Self {
Self::new(vec![
Color::new(0xA3, 0x51, 0xFB),
Color::new(0xFF, 0x64, 0x37),
Color::new(0x00, 0xD4, 0xBB),
Color::new(0xFF, 0xD7, 0x00),
Color::new(0xEF, 0x38, 0x8E),
Color::new(0x4A, 0xD1, 0x2C),
Color::new(0x2E, 0x86, 0xFF),
Color::new(0xFF, 0x8C, 0x00),
])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn by_class_id_is_stable() {
let palette = ColorPalette::default();
assert_eq!(palette.by_class_id(3), palette.by_class_id(3));
}
#[test]
fn by_class_id_wraps_around_palette_length() {
let palette = ColorPalette::default();
let len = palette.len();
assert_eq!(palette.by_class_id(0), palette.by_class_id(len));
}
#[test]
fn distinct_class_ids_within_palette_get_distinct_colors() {
let palette = ColorPalette::default();
assert_ne!(palette.by_class_id(0), palette.by_class_id(1));
}
#[test]
#[should_panic]
fn empty_palette_panics() {
ColorPalette::new(vec![]);
}
}