Skip to main content

rgb_sequencer/
types.rs

1//! Core types for sequence construction.
2
3use crate::time::TimeDuration;
4use palette::Srgb;
5
6/// How to transition to a step's target color.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum TransitionStyle {
9    /// Instantly jump to target color, hold for duration. Works with zero duration.
10    Step,
11
12    /// Linear interpolation over duration. Requires non-zero duration.
13    Linear,
14
15    /// Quadratic ease-in: slow start, accelerating toward end. Requires non-zero duration.
16    EaseIn,
17
18    /// Quadratic ease-out: fast start, decelerating toward end. Requires non-zero duration.
19    EaseOut,
20
21    /// Quadratic ease-in-out: slow start and end, fast middle. Requires non-zero duration.
22    EaseInOut,
23
24    /// Quadratic ease-out-in: fast start and end, slow middle. Requires non-zero duration.
25    EaseOutIn,
26}
27
28/// How many times a sequence should repeat.
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum LoopCount {
31    /// Repeat a specific number of times.
32    Finite(u32),
33
34    /// Repeat indefinitely.
35    Infinite,
36}
37
38impl Default for LoopCount {
39    /// Returns the default loop count (one iteration).
40    fn default() -> Self {
41        LoopCount::Finite(1)
42    }
43}
44
45/// A single step in an RGB sequence.
46#[derive(Debug, Clone, Copy)]
47pub struct SequenceStep<D: TimeDuration> {
48    /// Target color (0.0-1.0 range).
49    pub color: Srgb,
50
51    /// Step duration (how long to hold for Step, or interpolate over for Linear/easing).
52    pub duration: D,
53
54    /// Transition style (how to animate to this color).
55    pub transition: TransitionStyle,
56}
57
58impl<D: TimeDuration> SequenceStep<D> {
59    /// Creates a new sequence step.
60    #[inline]
61    pub fn new(color: Srgb, duration: D, transition: TransitionStyle) -> Self {
62        Self {
63            color,
64            duration,
65            transition,
66        }
67    }
68}
69
70/// Sequence validation errors.
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum SequenceError {
73    /// No steps provided.
74    EmptySequence,
75
76    /// Zero duration with interpolating transition.
77    ZeroDurationWithInterpolation,
78
79    /// Sequence capacity exceeded.
80    CapacityExceeded,
81
82    /// Start color set with first step using Step transition.
83    StartColorWithStepTransition,
84
85    /// Landing color set with infinite loop count.
86    LandingColorWithInfiniteLoop,
87}
88
89impl core::fmt::Display for SequenceError {
90    /// Formats the error for display.
91    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
92        match self {
93            SequenceError::EmptySequence => {
94                write!(f, "sequence must have at least one step")
95            }
96            SequenceError::ZeroDurationWithInterpolation => {
97                write!(
98                    f,
99                    "zero-duration steps must use Step transition (interpolating transitions require non-zero duration)"
100                )
101            }
102            SequenceError::CapacityExceeded => {
103                write!(f, "sequence capacity exceeded")
104            }
105            SequenceError::StartColorWithStepTransition => {
106                write!(
107                    f,
108                    "start_color only applies when first sequence step has TransitionStyle != Step"
109                )
110            }
111            SequenceError::LandingColorWithInfiniteLoop => {
112                write!(
113                    f,
114                    "landing_color only applies to finite sequences (infinite loops never complete)"
115                )
116            }
117        }
118    }
119}