1use thiserror::Error;
4
5use crate::IconId;
6
7#[non_exhaustive]
12#[derive(Debug, Error)]
13pub enum DesktopError {
14 #[error("desktop backend is unavailable: {0}")]
17 BackendUnavailable(String),
18
19 #[error("COM error (0x{hresult:08X}): {msg}")]
21 Com { hresult: u32, msg: String },
22
23 #[error("icon not found: {0}")]
25 IconNotFound(IconId),
26
27 #[error("invalid curve: {0}")]
29 InvalidCurve(#[from] CurveError),
30
31 #[error("invalid duration: {0}")]
33 InvalidDuration(String),
34
35 #[error("cannot resolve desktop grid: {0}")]
36 InvalidGrid(String),
37
38 #[error("invalid effect: {0}")]
40 InvalidEffect(String),
41
42 #[error("this platform is not supported by any compiled backend")]
44 UnsupportedPlatform,
45
46 #[error("animation worker crashed: {0}")]
48 WorkerCrashed(String),
49
50 #[error("another animation is already running")]
53 AnimationBusy,
54
55 #[error("overlay renderer unavailable: {0}")]
61 OverlayUnavailable(String),
62
63 #[error("overlay animation cancelled: {0}")]
75 OverlayCancelled(String),
76}
77
78#[non_exhaustive]
80#[derive(Debug, Error, PartialEq)]
81pub enum CurveError {
82 #[error("keyframe curve must contain at least 2 keys, got {0}")]
83 TooFewKeys(usize),
84
85 #[error(
86 "keyframe times must be strictly ascending in [0, 1] \
87 (bad key at index {index}: t = {t})"
88 )]
89 InvalidKeyOrder { index: usize, t: f32 },
90
91 #[error("first keyframe must have t = 0.0, got t = {0}")]
92 FirstKeyNotZero(f32),
93
94 #[error("last keyframe must have t = 1.0, got t = {0}")]
95 LastKeyNotOne(f32),
96
97 #[error("keyframe value is not finite (index {index}, t = {t}, v = {v})")]
98 NonFiniteValue { index: usize, t: f32, v: f32 },
99
100 #[error(
101 "sampled function returned an out-of-range or non-finite value at t = {t}: v = {v}"
102 )]
103 SampledValueInvalid { t: f32, v: f32 },
104
105 #[error("sample count out of bounds: got {got}, expected 2..=4096")]
106 InvalidSampleCount { got: u32 },
107
108 #[error(
109 "invalid cubic-Bézier control points: c1x = {c1x}, c2x = {c2x} \
110 (both must lie in [0, 1])"
111 )]
112 InvalidBezier { c1x: f32, c2x: f32 },
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn desktop_error_display_covers_variants() {
121 assert!(format!("{}", DesktopError::UnsupportedPlatform).contains("platform"));
122 assert!(format!("{}", DesktopError::AnimationBusy).contains("already running"));
123 let e = DesktopError::Com {
124 hresult: 0x8000_4005,
125 msg: "boom".into(),
126 };
127 assert!(format!("{e}").contains("0x80004005"));
128 }
129
130 #[test]
131 fn curve_error_into_desktop_error_via_from() {
132 let e: DesktopError = CurveError::TooFewKeys(1).into();
133 assert!(matches!(e, DesktopError::InvalidCurve(_)));
134 }
135}