Skip to main content

aseprite/
error.rs

1use std::fmt;
2use std::io;
3
4/// Errors that can occur when reading or writing Aseprite files.
5#[derive(Debug)]
6pub enum AsepriteError {
7    /// An I/O error occurred during reading or writing.
8    Io(io::Error),
9    /// The file does not start with the Aseprite magic number `0xA5E0`.
10    InvalidMagic,
11    /// The file uses a color depth that is not 8, 16, or 32 bits.
12    UnsupportedColorDepth(u16),
13    /// A frame index is out of bounds.
14    FrameOutOfBounds(usize),
15    /// Pixel data buffer size does not match the expected size for the given dimensions and color mode.
16    PixelSizeMismatch { expected: usize, actual: usize },
17    /// A tag's frame range extends beyond the number of frames in the file.
18    InvalidFrameRange,
19    /// Indexed color mode requires a palette, but none was set.
20    MissingPalette,
21    /// A linked cel references a source frame that does not contain a cel on the same layer.
22    LinkedCelNotFound { layer: usize, source_frame: usize },
23    /// A chunk's declared size is invalid.
24    InvalidChunkSize,
25    /// A chunk or property type ID is not recognized.
26    UnsupportedChunkType(u16),
27    /// A value exceeds the format's limit (e.g., more than 256 palette entries).
28    FormatLimitExceeded {
29        field: &'static str,
30        value: usize,
31        max: usize,
32    },
33}
34
35impl fmt::Display for AsepriteError {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::Io(e) => write!(f, "I/O error: {e}"),
39            Self::InvalidMagic => write!(f, "invalid magic number (expected 0xA5E0)"),
40            Self::UnsupportedColorDepth(d) => write!(f, "unsupported color depth: {d}"),
41            Self::FrameOutOfBounds(i) => write!(f, "frame index {i} out of bounds"),
42            Self::PixelSizeMismatch { expected, actual } => {
43                write!(
44                    f,
45                    "pixel data size mismatch: expected {expected}, got {actual}"
46                )
47            }
48            Self::InvalidFrameRange => write!(f, "invalid frame range"),
49            Self::MissingPalette => write!(f, "indexed color mode requires a palette"),
50            Self::LinkedCelNotFound {
51                layer,
52                source_frame,
53            } => {
54                write!(
55                    f,
56                    "linked cel not found: layer {layer}, source frame {source_frame}"
57                )
58            }
59            Self::InvalidChunkSize => write!(f, "invalid chunk size"),
60            Self::UnsupportedChunkType(t) => write!(f, "unsupported chunk type: 0x{t:04X}"),
61            Self::FormatLimitExceeded { field, value, max } => {
62                write!(f, "format limit exceeded for {field}: {value} > {max}")
63            }
64        }
65    }
66}
67
68impl std::error::Error for AsepriteError {
69    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
70        match self {
71            Self::Io(e) => Some(e),
72            _ => None,
73        }
74    }
75}
76
77impl From<io::Error> for AsepriteError {
78    fn from(e: io::Error) -> Self {
79        Self::Io(e)
80    }
81}