Skip to main content

alpha2_engine/
error.rs

1use std::fmt;
2
3/// Failure produced by an engine runner.
4#[derive(Clone, Debug, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum EngineError {
7    /// Timeline evaluation failed.
8    Evaluate(alpha2_eval::EvalError),
9    /// GPU rendering failed.
10    Render(alpha2_render::RenderError),
11    /// A quality profile contains an unusable value.
12    InvalidQualityProfile,
13    /// A frame index or scaled output size cannot be represented.
14    OutOfRange,
15    /// An exporter requires a non-empty timeline interval.
16    EmptyExportRange,
17    /// An export schedule exceeds the bounded frame budget.
18    ExportTooLarge {
19        /// Requested frame count.
20        frames: u64,
21        /// Largest supported frame count.
22        maximum: u64,
23    },
24    /// A caption or a text generator could not be rasterized or uploaded.
25    Text(crate::TextError),
26    /// An audio renderer received an unsupported layout, rate, or block size.
27    InvalidAudioConfiguration,
28    /// A loudness normalization gain whose linear factor is not a finite positive `f32`.
29    InvalidNormalizationGain,
30    /// The project draws an effect the renderer has not registered (or failed to register).
31    UnregisteredEffect {
32        /// The effect's id.
33        effect: String,
34        /// Its version.
35        version: u32,
36    },
37    /// An export step was given a different snapshot than its exporter's.
38    ExportProjectChanged,
39    /// A 4:2:0 export was asked for an output with an odd width or height.
40    ///
41    /// Chroma planes are half size and H.264/HEVC crop in two-pixel steps. The canvas may be odd;
42    /// making the output even is the host's choice.
43    OddExportDimensions {
44        /// Output width.
45        width: u32,
46        /// Output height.
47        height: u32,
48        /// The nearest even size: odd dimensions one pixel smaller (larger if one pixel).
49        suggested: (u32, u32),
50    },
51}
52
53impl fmt::Display for EngineError {
54    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
55        match self {
56            Self::Evaluate(error) => write!(formatter, "timeline evaluation failed: {error}"),
57            Self::Render(error) => write!(formatter, "rendering failed: {error}"),
58            Self::InvalidQualityProfile => formatter.write_str("quality profile is invalid"),
59            Self::OutOfRange => formatter.write_str("timeline or output size is out of range"),
60            Self::EmptyExportRange => formatter.write_str("export range must not be empty"),
61            Self::ExportTooLarge { frames, maximum } => write!(
62                formatter,
63                "export requests {frames} frames; the maximum is {maximum}"
64            ),
65            Self::Text(error) => write!(formatter, "{error}"),
66            Self::InvalidAudioConfiguration => {
67                formatter.write_str("audio channel layout, sample rate, or block size is invalid")
68            }
69            Self::InvalidNormalizationGain => formatter.write_str(
70                "loudness normalization gain is not finite or past what a 32-bit float factor holds",
71            ),
72            Self::UnregisteredEffect { effect, version } => write!(
73                formatter,
74                "the project draws effect {effect}@{version}, which is not registered"
75            ),
76            Self::ExportProjectChanged => formatter.write_str(
77                "an export step was given another project than the export was started with",
78            ),
79            Self::OddExportDimensions {
80                width,
81                height,
82                suggested: (suggested_width, suggested_height),
83            } => write!(
84                formatter,
85                "4:2:0 video export must have even dimensions, but the output is \
86                 {width}x{height}; the nearest even size is {suggested_width}x{suggested_height}"
87            ),
88        }
89    }
90}
91
92impl std::error::Error for EngineError {
93    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
94        match self {
95            Self::Evaluate(error) => Some(error),
96            Self::Render(error) => Some(error),
97            _ => None,
98        }
99    }
100}
101
102impl From<alpha2_eval::EvalError> for EngineError {
103    fn from(error: alpha2_eval::EvalError) -> Self {
104        Self::Evaluate(error)
105    }
106}
107
108impl From<alpha2_render::RenderError> for EngineError {
109    fn from(error: alpha2_render::RenderError) -> Self {
110        Self::Render(error)
111    }
112}