Skip to main content

martin_core/tiles/hillshade/
error.rs

1//! The error space of a hillshade bake.
2
3use martin_tile_utils::Format;
4
5use crate::tiles::neighbourhood::NeighbourhoodError;
6
7/// Errors raised while assembling, baking, or encoding a hillshade tile.
8#[derive(thiserror::Error, Debug)]
9#[non_exhaustive]
10pub enum HillshadeError {
11    /// The centre tile was fetched successfully but could not be decoded as an image.
12    #[error(
13        "The centre normal tile was fetched but could not be decoded as an image. \
14         The upstream source served malformed data for this tile."
15    )]
16    CorruptCentreTile,
17
18    /// A bake produced a buffer that did not match its own declared dimensions.
19    #[error(
20        "Baked hillshade is {actual} bytes but its {side}x{side} dimensions require {expected}"
21    )]
22    MalformedBake {
23        /// Byte length produced.
24        actual: usize,
25        /// Byte length the declared dimensions require.
26        expected: usize,
27        /// Declared side length in pixels.
28        side: u32,
29    },
30
31    /// A format was requested that the hillshade encoder cannot produce.
32    #[error(
33        "Hillshade cannot be encoded as {0}. Supported formats are png, webp, and jxl, \
34         all lossless. A hillshade is multiplied over the basemap, so a lossy \
35         codec would show visible blotches on flat terrain."
36    )]
37    UnsupportedFormat(Format),
38
39    /// Encoding the baked grayscale image failed.
40    #[error("Failed to encode the baked hillshade as {format}: {source}")]
41    Encoding {
42        /// Target image format.
43        format: Format,
44        /// Underlying encoder error.
45        source: image::ImageError,
46    },
47}
48
49impl From<NeighbourhoodError> for HillshadeError {
50    fn from(value: NeighbourhoodError) -> Self {
51        match value {
52            NeighbourhoodError::CorruptCentreTile => Self::CorruptCentreTile,
53        }
54    }
55}
56
57impl crate::Classify for HillshadeError {
58    fn kind(&self) -> crate::ErrorKind {
59        use crate::ErrorKind::{Internal, InvalidInput, Unavailable};
60        match self {
61            Self::CorruptCentreTile => Unavailable,
62            Self::UnsupportedFormat(_) => InvalidInput,
63            Self::MalformedBake { .. } | Self::Encoding { .. } => Internal,
64        }
65    }
66}