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}