erebus 0.1.8

A CLI message generation library
Documentation
// Originally from ariadne (https://github.com/zesterer/ariadne)
// Used under the MIT license

use yansi::Color;

/// A type that can generate distinct 8-bit colors.
pub struct ColorGenerator {
    state: [u16; 3],
    min_brightness: f32,
}

impl Default for ColorGenerator {
    fn default() -> Self {
        Self::from_state([5000, 5000, 20000], 0.5)
    }
}

impl ColorGenerator {
    #[must_use]
    /// Create a new [`ColorGenerator`] with the given pre-chosen state.
    ///
    /// The minimum brightness can be used to control the colour brightness (0.0 - 1.0). The default is 0.5.
    pub fn from_state(state: [u16; 3], min_brightness: f32) -> Self {
        Self {
            state,
            min_brightness: min_brightness.clamp(0.0, 1.0),
        }
    }

    #[must_use]
    /// Create a new [`ColorGenerator`] with the default state.
    pub fn new() -> Self {
        Self::default()
    }

    /// Generate the next colour in the sequence.
    #[allow(clippy::should_implement_trait)]
    pub fn next(&mut self) -> Color {
        #[allow(clippy::cast_possible_truncation)]
        for i in 0..3 {
            // magic constant, one of only two that have this property!
            self.state[i] = (self.state[i] as usize).wrapping_add(40503 * (i * 4 + 1130)) as u16;
        }
        #[allow(clippy::cast_possible_truncation)]
        #[allow(clippy::cast_sign_loss)]
        Color::Fixed(
            16 + (f32::from(self.state[0]) / 65535.0)
                .mul_add(1.0 - self.min_brightness, self.min_brightness)
                .mul_add(
                    180.0,
                    (f32::from(self.state[2]) / 65535.0)
                        .mul_add(1.0 - self.min_brightness, self.min_brightness)
                        .mul_add(
                            5.0,
                            (f32::from(self.state[1]) / 65535.0)
                                .mul_add(1.0 - self.min_brightness, self.min_brightness)
                                * 30.0,
                        ),
                ) as u8,
        )
    }
}

impl Iterator for ColorGenerator {
    type Item = Color;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.next())
    }
}