Skip to main content

kallo_api/
error.rs

1//! Failures a user can cause, with enough context to fix them.
2
3use std::path::PathBuf;
4
5use kallo_io::IoError;
6
7/// Everything the model can fail at.
8#[derive(Debug)]
9pub enum Error {
10    /// The requested stock id is not compiled in.
11    UnknownStock {
12        /// `"film"` or `"paper"`.
13        kind: &'static str,
14        /// The id the user typed.
15        id: String,
16    },
17    /// A numeric flag received a value outside its domain.
18    InvalidNumber {
19        /// The flag, e.g. `"--dev"`.
20        flag: &'static str,
21        /// The value the user typed.
22        value: f64,
23        /// What was expected, e.g. `"a positive number of minutes"`.
24        expected: &'static str,
25    },
26    /// The output directory could not be created.
27    CreateDir {
28        /// The directory that failed.
29        path: PathBuf,
30        /// The underlying OS error.
31        source: std::io::Error,
32    },
33    /// A camera raw file could not be decoded.
34    Raw {
35        /// The file that failed.
36        path: PathBuf,
37        /// What the decoder said.
38        message: String,
39    },
40    /// The input could not be decoded.
41    Read {
42        /// The file that failed.
43        path: PathBuf,
44        /// The underlying decoder error.
45        source: IoError,
46    },
47    /// A `.kalofilm` file could not be read or verified.
48    Film {
49        /// The file that failed.
50        path: PathBuf,
51        /// What the loader said.
52        message: String,
53    },
54    /// A stock file could not be read, parsed or checked.
55    Stock {
56        /// The file that failed.
57        path: PathBuf,
58        /// What the checker said.
59        message: String,
60    },
61    /// The dictionary could not be read.
62    Dictionary {
63        /// The file that failed.
64        path: PathBuf,
65        /// What the loader said.
66        message: String,
67    },
68    /// The build has no GPU backend, or the one it has cannot run this render.
69    Gpu {
70        /// What to tell the user.
71        message: String,
72    },
73    /// A camera sensitivity file could not be read.
74    Camera {
75        /// The file that failed.
76        path: PathBuf,
77        /// What went wrong.
78        message: String,
79    },
80    /// A baked table could not be read or written.
81    Lut {
82        /// The file that failed.
83        path: PathBuf,
84        /// What the table layer said.
85        message: String,
86    },
87    /// A contact proof could not be made, or its record written.
88    Contact {
89        /// What to tell the user.
90        message: String,
91    },
92    /// The output could not be encoded.
93    Write {
94        /// The file that failed.
95        path: PathBuf,
96        /// The underlying encoder error.
97        source: IoError,
98    },
99}
100
101impl std::fmt::Display for Error {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        match self {
104            Self::UnknownStock { kind, id } => {
105                write!(f, "unknown {kind} stock '{id}' (try `kalo stocks`)")
106            }
107            Self::InvalidNumber {
108                flag,
109                value,
110                expected,
111            } => {
112                write!(f, "{flag} must be {expected}, got {value}")
113            }
114            Self::CreateDir { path, source } => {
115                write!(f, "could not create {}: {source}", path.display())
116            }
117            Self::Raw { path, message } => {
118                write!(f, "could not decode raw file {}: {message}", path.display())
119            }
120            Self::Read { path, source } => {
121                write!(f, "could not read {}: {source}", path.display())
122            }
123            Self::Film { path, message } => {
124                write!(f, "could not load film {}: {message}", path.display())
125            }
126            Self::Dictionary { path, message } => {
127                write!(f, "could not read dictionary {}: {message}", path.display())
128            }
129            Self::Stock { path, message } => {
130                write!(f, "stock {}: {message}", path.display())
131            }
132            Self::Gpu { message } => write!(f, "{message}"),
133            Self::Camera { path, message } => {
134                write!(f, "camera sensitivity {}: {message}", path.display())
135            }
136            Self::Lut { path, message } => {
137                write!(f, "lookup table {}: {message}", path.display())
138            }
139            Self::Contact { message } => write!(f, "{message}"),
140            Self::Write { path, source } => {
141                write!(f, "could not write {}: {source}", path.display())
142            }
143        }
144    }
145}
146
147impl std::error::Error for Error {
148    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
149        match self {
150            Self::CreateDir { source, .. } => Some(source),
151            Self::Read { source, .. } | Self::Write { source, .. } => Some(source),
152            Self::UnknownStock { .. }
153            | Self::InvalidNumber { .. }
154            | Self::Film { .. }
155            | Self::Raw { .. }
156            | Self::Dictionary { .. }
157            | Self::Camera { .. }
158            | Self::Gpu { .. }
159            | Self::Lut { .. }
160            | Self::Stock { .. }
161            | Self::Contact { .. } => None,
162        }
163    }
164}