Skip to main content

lumen_engine/
error.rs

1//! Error types and diagnostics for the Lumen compositing engine.
2
3use thiserror::Error;
4
5use crate::node::{NodeId, PortKind};
6
7#[derive(Debug, Error, Clone)]
8pub enum LumenError {
9    #[error("graph validation error: {0}")]
10    GraphValidation(#[from] GraphValidationError),
11    #[error("property resolution error: {0}")]
12    Property(#[from] PropertyError),
13    #[error("expression error: {0}")]
14    Expression(#[from] ExpressionError),
15    #[error("media error: {0}")]
16    Media(#[from] MediaError),
17    #[error("render error: {0}")]
18    Render(#[from] RenderError),
19}
20
21#[derive(Debug, Error, Clone)]
22pub enum GraphValidationError {
23    #[error("graph contains a cycle")]
24    Cycle { path: Vec<NodeId> },
25    #[error("connection target node is missing")]
26    MissingTargetNode { node_id: NodeId },
27    #[error("connection source node is missing")]
28    MissingSourceNode { node_id: NodeId },
29    #[error("connection target port `{port}` is missing")]
30    MissingTargetPort { node_id: NodeId, port: String },
31    #[error("connection source port `{port}` is missing")]
32    MissingSourcePort { node_id: NodeId, port: String },
33    #[error("missing required input `{port}`")]
34    MissingRequiredInput { node_id: NodeId, port: String },
35    #[error("port kind mismatch for `{to_port}`")]
36    PortKindMismatch {
37        from_node: NodeId,
38        from_port: String,
39        from_kind: PortKind,
40        to_node: NodeId,
41        to_port: String,
42        expected_kind: PortKind,
43    },
44    #[error("exactly one media output node is required")]
45    MissingMediaOutput,
46    #[error("exactly one media output node is required")]
47    MultipleMediaOutputs { count: usize },
48    #[error("target node is not reachable or missing")]
49    InvalidEvaluationTarget { node_id: NodeId },
50}
51
52#[derive(Debug, Error, Clone)]
53pub enum PropertyError {
54    #[error("property `{property_path}` is missing")]
55    MissingProperty {
56        node_id: NodeId,
57        property_path: String,
58    },
59    #[error("property `{property_path}` has invalid type")]
60    InvalidType {
61        node_id: NodeId,
62        property_path: String,
63        expected: &'static str,
64        actual: &'static str,
65    },
66}
67
68#[derive(Debug, Error, Clone)]
69pub enum ExpressionError {
70    #[error("expression parse failed: {details}")]
71    Parse {
72        path: Option<String>,
73        details: String,
74    },
75    #[error("expression evaluation failed: {details}")]
76    Evaluate {
77        path: Option<String>,
78        details: String,
79    },
80    #[error("undefined variable in expression")]
81    UndefinedVariable { path: Option<String>, name: String },
82}
83
84#[derive(Debug, Error, Clone)]
85pub enum MediaError {
86    #[error("media source not found: {media_source}")]
87    SourceNotFound { media_source: String },
88    #[error("media decoding failed for {media_source}: {details}")]
89    Decode {
90        media_source: String,
91        details: String,
92    },
93    #[error("media frame {frame} is out of range for {media_source} ({frame_count} frames)")]
94    FrameOutOfRange {
95        media_source: String,
96        frame: u32,
97        frame_count: u32,
98    },
99}
100
101#[derive(Debug, Error, Clone)]
102pub enum RenderError {
103    #[error("frame is out of range")]
104    FrameOutOfRange { frame: u32, duration_frames: u32 },
105    #[error("node evaluation failed")]
106    NodeEvaluation {
107        frame: u32,
108        node_id: NodeId,
109        node_kind: &'static str,
110        details: String,
111    },
112    #[error("referenced node is missing from the graph")]
113    MissingNode { frame: u32, node_id: NodeId },
114    #[error("surface allocation failed")]
115    SurfaceAllocation { width: u32, height: u32 },
116    #[error("node output is missing")]
117    MissingNodeOutput { frame: u32, node_id: NodeId },
118    #[error("node output has invalid type")]
119    InvalidNodeOutputType {
120        frame: u32,
121        node_id: NodeId,
122        expected: &'static str,
123        actual: &'static str,
124    },
125    #[error("media output node did not produce raster output")]
126    InvalidMediaOutputType { frame: u32, node_id: NodeId },
127    #[error("pixel readback failed")]
128    PixelReadbackFailed { width: u32, height: u32 },
129    #[error("all scratch surfaces are currently in use")]
130    ScratchSurfaceUnavailable,
131    #[error("{backend} backend is busy")]
132    BackendBusy { backend: &'static str },
133    #[error("render cancelled")]
134    Cancelled { frame: u32 },
135    #[error("GPU render failed: {details}")]
136    Gpu { details: String },
137}
138
139#[derive(Debug, Clone, PartialEq)]
140pub enum Warning {
141    FpsMismatch {
142        node_id: NodeId,
143        composition_fps: f32,
144        source_fps: f32,
145    },
146    CapabilityMissing {
147        node_id: NodeId,
148        requirement: &'static str,
149    },
150}