1#[derive(Debug)]
2pub struct UnknownError {
3 pub name: String,
4 pub value: String,
5 pub expected: Vec<(Vec<String>, String)>,
6}
7
8impl std::fmt::Display for UnknownError {
9 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10 write!(
11 f,
12 "Unknown {} variant {}. \nexpected: ",
13 self.name, self.value
14 )?;
15
16 for (items, name) in self.expected.iter() {
17 write!(f, "\n- ")?;
18
19 for (index, item) in items.iter().enumerate() {
20 write!(
21 f,
22 "{}{}",
23 item,
24 if index == items.len() - 1 { "" } else { " | " }
25 )?;
26 }
27
28 write!(f, " => {}.", name)?;
29 }
30
31 Ok(())
32 }
33}
34
35impl std::error::Error for UnknownError {}
36
37#[derive(Debug)]
38pub struct MissingFieldError(pub String);
39
40impl std::fmt::Display for MissingFieldError {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(f, "Did not set the field \"{}\" when building", self.0)
43 }
44}
45
46impl std::error::Error for MissingFieldError {}
47
48#[derive(Debug)]
49pub enum StitchError {
50 MissingField(MissingFieldError),
51 NotEnoughImages(usize),
52 InvalidWindowSize,
53 ImageTooSmall {
54 width: u32,
55 height: u32,
56 window_size: u32,
57 crop: u32,
58 },
59 ScoreOverflow {
60 window_size: u32,
61 max_width: u32,
62 },
63 NoAdapter(String),
64 Gpu(String),
65 NoCandidates,
66}
67
68impl std::fmt::Display for StitchError {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 match self {
71 Self::MissingField(err) => err.fmt(f),
72 Self::NotEnoughImages(count) => {
73 write!(f, "Need at least two images to stitch, got {count}")
74 }
75 Self::InvalidWindowSize => write!(f, "Window size must be at least 1"),
76 Self::ImageTooSmall {
77 width,
78 height,
79 window_size,
80 crop,
81 } => write!(
82 f,
83 "Image of size {width}x{height} is too small for window size {window_size} with crop {crop}"
84 ),
85 Self::ScoreOverflow {
86 window_size,
87 max_width,
88 } => write!(
89 f,
90 "Window size {window_size} with image width {max_width} would overflow the score accumulator, use a smaller window"
91 ),
92 Self::NoAdapter(details) => write!(
93 f,
94 "No compatible GPU adapter found (WebGPU/DX12/Vulkan/Metal required): {details}"
95 ),
96 Self::Gpu(details) => write!(f, "GPU error: {details}"),
97 Self::NoCandidates => write!(
98 f,
99 "No overlap candidates to score, images do not leave room for the search window"
100 ),
101 }
102 }
103}
104
105impl std::error::Error for StitchError {}
106
107impl From<MissingFieldError> for StitchError {
108 fn from(err: MissingFieldError) -> Self {
109 Self::MissingField(err)
110 }
111}
112
113macro_rules! unknown_error_expected {
114 ($($head:literal $(| $tail:literal)* => $type:literal),*) => {
115 vec![
116 $(
117 (
118 vec![$head.to_string() $(, $tail.to_string())*],
119 $type.to_string()
120 )
121 ),*
122 ]
123 };
124}
125
126pub(crate) use unknown_error_expected;