rgb-sequencer 0.2.1

A no_std-compatible Rust library for controlling RGB LEDs through timed color sequences on embedded systems
Documentation
//! Core types for sequence construction.

use crate::time::TimeDuration;
use palette::Srgb;

/// How to transition to a step's target color.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransitionStyle {
    /// Instantly jump to target color, hold for duration. Works with zero duration.
    Step,

    /// Linear interpolation over duration. Requires non-zero duration.
    Linear,

    /// Quadratic ease-in: slow start, accelerating toward end. Requires non-zero duration.
    EaseIn,

    /// Quadratic ease-out: fast start, decelerating toward end. Requires non-zero duration.
    EaseOut,

    /// Quadratic ease-in-out: slow start and end, fast middle. Requires non-zero duration.
    EaseInOut,

    /// Quadratic ease-out-in: fast start and end, slow middle. Requires non-zero duration.
    EaseOutIn,
}

/// How many times a sequence should repeat.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LoopCount {
    /// Repeat a specific number of times.
    Finite(u32),

    /// Repeat indefinitely.
    Infinite,
}

impl Default for LoopCount {
    /// Returns the default loop count (one iteration).
    fn default() -> Self {
        LoopCount::Finite(1)
    }
}

/// A single step in an RGB sequence.
#[derive(Debug, Clone, Copy)]
pub struct SequenceStep<D: TimeDuration> {
    /// Target color (0.0-1.0 range).
    pub color: Srgb,

    /// Step duration (how long to hold for Step, or interpolate over for Linear/easing).
    pub duration: D,

    /// Transition style (how to animate to this color).
    pub transition: TransitionStyle,
}

impl<D: TimeDuration> SequenceStep<D> {
    /// Creates a new sequence step.
    #[inline]
    pub fn new(color: Srgb, duration: D, transition: TransitionStyle) -> Self {
        Self {
            color,
            duration,
            transition,
        }
    }
}

/// Sequence validation errors.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SequenceError {
    /// No steps provided.
    EmptySequence,

    /// Zero duration with interpolating transition.
    ZeroDurationWithInterpolation,

    /// Sequence capacity exceeded.
    CapacityExceeded,

    /// Start color set with first step using Step transition.
    StartColorWithStepTransition,

    /// Landing color set with infinite loop count.
    LandingColorWithInfiniteLoop,
}

impl core::fmt::Display for SequenceError {
    /// Formats the error for display.
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            SequenceError::EmptySequence => {
                write!(f, "sequence must have at least one step")
            }
            SequenceError::ZeroDurationWithInterpolation => {
                write!(
                    f,
                    "zero-duration steps must use Step transition (interpolating transitions require non-zero duration)"
                )
            }
            SequenceError::CapacityExceeded => {
                write!(f, "sequence capacity exceeded")
            }
            SequenceError::StartColorWithStepTransition => {
                write!(
                    f,
                    "start_color only applies when first sequence step has TransitionStyle != Step"
                )
            }
            SequenceError::LandingColorWithInfiniteLoop => {
                write!(
                    f,
                    "landing_color only applies to finite sequences (infinite loops never complete)"
                )
            }
        }
    }
}