Skip to main content

j2k_core/
error.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::{pixel::PixelFormat, sample::SampleType};
4
5/// Buffer validation and copy errors.
6#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
7#[non_exhaustive]
8pub enum BufferError {
9    /// Destination buffer is too small for the requested output.
10    #[error("output buffer too small: required {required} bytes, have {have}")]
11    OutputTooSmall {
12        /// Required destination length in bytes.
13        required: usize,
14        /// Actual destination length in bytes.
15        have: usize,
16    },
17    /// Source buffer is too small for the requested copy/decode.
18    #[error("input buffer too small: required {required} bytes, have {have}")]
19    InputTooSmall {
20        /// Required source length in bytes.
21        required: usize,
22        /// Actual source length in bytes.
23        have: usize,
24    },
25    /// A byte-count computation overflowed.
26    #[error("buffer size overflow while computing {what}")]
27    SizeOverflow {
28        /// Name of the size being computed.
29        what: &'static str,
30    },
31    /// A requested allocation exceeds the configured safety cap.
32    #[error("{what} allocation too large: requested {requested} bytes, cap {cap}")]
33    AllocationTooLarge {
34        /// Requested byte count.
35        requested: usize,
36        /// Configured byte cap.
37        cap: usize,
38        /// Name of the allocation being checked.
39        what: &'static str,
40    },
41    /// The host allocator could not reserve a cap-valid buffer.
42    #[error("host allocation failed for {bytes} bytes while allocating {what}")]
43    HostAllocationFailed {
44        /// Requested host byte count.
45        bytes: usize,
46        /// Name of the allocation that failed.
47        what: &'static str,
48    },
49    /// Output stride cannot hold one decoded row.
50    #[error("stride {stride} is smaller than row width {row_bytes}")]
51    StrideTooSmall {
52        /// Required row width in bytes.
53        row_bytes: usize,
54        /// Supplied stride in bytes.
55        stride: usize,
56    },
57    /// Output stride does not meet backend alignment requirements.
58    #[error("stride {stride} is not aligned to {align}")]
59    StrideNotAligned {
60        /// Supplied stride in bytes.
61        stride: usize,
62        /// Required byte alignment.
63        align: usize,
64    },
65    /// Requested pixel format uses a different sample width than the row type.
66    #[error("pixel format {fmt:?} does not match sample type {sample_type:?}")]
67    SampleTypeMismatch {
68        /// Requested output pixel format.
69        fmt: PixelFormat,
70        /// Sample type accepted by the current sink or buffer.
71        sample_type: SampleType,
72    },
73}
74
75/// Generic malformed or truncated input errors.
76#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
77pub enum InputError {
78    /// Input ended before a required fixed-size read.
79    #[error("input too short: need {need} bytes, have {have}")]
80    TooShort {
81        /// Required byte count.
82        need: usize,
83        /// Available byte count.
84        have: usize,
85    },
86    /// Input ended while reading a named segment.
87    #[error("input truncated at offset {offset} while reading {segment}")]
88    TruncatedAt {
89        /// Byte offset where truncation was detected.
90        offset: usize,
91        /// Name of the segment being read.
92        segment: &'static str,
93    },
94}
95
96/// Error for a valid request that is not implemented yet.
97#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
98#[error("not yet implemented: {what}")]
99pub struct NotImplemented {
100    /// Feature or path that is not implemented.
101    pub what: &'static str,
102}
103
104/// Error for input or options unsupported by the current codec.
105#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
106#[error("unsupported: {what}")]
107pub struct Unsupported {
108    /// Unsupported feature or option.
109    pub what: &'static str,
110}
111
112/// Shared error classification used by facade traits.
113pub trait CodecError: core::error::Error + Send + Sync + 'static {
114    /// True when the error indicates truncated input.
115    fn is_truncated(&self) -> bool;
116    /// True when the error indicates an unimplemented supported surface.
117    fn is_not_implemented(&self) -> bool;
118    /// True when the error indicates unsupported input or options.
119    fn is_unsupported(&self) -> bool;
120    /// True when the error indicates caller buffer sizing or layout problems.
121    fn is_buffer_error(&self) -> bool;
122}
123
124/// Backend-adapter-local error classification.
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
126#[non_exhaustive]
127pub enum AdapterErrorKind {
128    /// Error is not a shared adapter classification.
129    Other,
130    /// Error is a caller buffer sizing or layout problem.
131    Buffer,
132    /// Error is an unsupported backend, request, input, or host capability.
133    Unsupported,
134}
135
136/// Variant mapping supplied by GPU adapter error enums.
137pub trait AdapterErrorParts {
138    /// Return the wrapped codec/fallback error, when this adapter error has one.
139    fn source_codec_error(&self) -> Option<&dyn CodecError>;
140
141    /// Return the adapter-local classification for non-codec variants.
142    fn adapter_error_kind(&self) -> AdapterErrorKind;
143}
144
145/// Shared truncated-input classification for adapter errors.
146#[doc(hidden)]
147pub fn adapter_error_is_truncated(error: &impl AdapterErrorParts) -> bool {
148    error
149        .source_codec_error()
150        .is_some_and(CodecError::is_truncated)
151}
152
153/// Shared not-implemented classification for adapter errors.
154#[doc(hidden)]
155pub fn adapter_error_is_not_implemented(error: &impl AdapterErrorParts) -> bool {
156    error
157        .source_codec_error()
158        .is_some_and(CodecError::is_not_implemented)
159}
160
161/// Shared unsupported classification for adapter errors.
162#[doc(hidden)]
163pub fn adapter_error_is_unsupported(error: &impl AdapterErrorParts) -> bool {
164    error.adapter_error_kind() == AdapterErrorKind::Unsupported
165        || error
166            .source_codec_error()
167            .is_some_and(CodecError::is_unsupported)
168}
169
170/// Shared buffer classification for adapter errors.
171#[doc(hidden)]
172pub fn adapter_error_is_buffer_error(error: &impl AdapterErrorParts) -> bool {
173    error.adapter_error_kind() == AdapterErrorKind::Buffer
174        || error
175            .source_codec_error()
176            .is_some_and(CodecError::is_buffer_error)
177}