Skip to main content

j2k_metal/error/
native_source.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3#[cfg(any(test, target_os = "macos"))]
4use j2k_native::{DecodeError, DecodeErrorClass, EncodeError};
5
6/// Opaque, Metal-adapter-owned source for native codec failures.
7///
8/// The concrete native error remains available through
9/// [`core::error::Error::source`] without becoming part of this crate's public
10/// type signatures. Classify the enclosing [`crate::Error`] through
11/// [`j2k_core::CodecError`].
12#[derive(Debug, PartialEq, Eq)]
13pub struct NativeBackendError {
14    #[cfg(any(test, target_os = "macos"))]
15    source: NativeBackendErrorSource,
16    #[cfg(not(any(test, target_os = "macos")))]
17    source: core::convert::Infallible,
18}
19
20#[cfg(any(test, target_os = "macos"))]
21#[derive(Debug, PartialEq, Eq)]
22enum NativeBackendErrorSource {
23    Decode(DecodeError),
24    Encode(EncodeError),
25}
26
27#[cfg(any(test, target_os = "macos"))]
28impl NativeBackendError {
29    pub(crate) const fn decode(source: DecodeError) -> Self {
30        Self {
31            source: NativeBackendErrorSource::Decode(source),
32        }
33    }
34
35    pub(crate) const fn encode(source: EncodeError) -> Self {
36        Self {
37            source: NativeBackendErrorSource::Encode(source),
38        }
39    }
40
41    pub(crate) fn is_decode_truncated(&self) -> bool {
42        matches!(
43            &self.source,
44            NativeBackendErrorSource::Decode(source)
45                if matches!(
46                    source.classify(),
47                    DecodeErrorClass::InputTooShort { .. }
48                        | DecodeErrorClass::InputTruncatedAt { .. }
49                )
50        )
51    }
52
53    pub(crate) fn is_unsupported(&self) -> bool {
54        match &self.source {
55            NativeBackendErrorSource::Decode(source) => {
56                matches!(source.classify(), DecodeErrorClass::Unsupported { .. })
57            }
58            NativeBackendErrorSource::Encode(EncodeError::Unsupported { .. }) => true,
59            NativeBackendErrorSource::Encode(_) => false,
60        }
61    }
62}
63
64#[cfg(not(any(test, target_os = "macos")))]
65impl NativeBackendError {
66    pub(crate) fn is_decode_truncated(&self) -> bool {
67        match self.source {}
68    }
69
70    pub(crate) fn is_unsupported(&self) -> bool {
71        match self.source {}
72    }
73}
74
75#[cfg(any(test, target_os = "macos"))]
76impl core::fmt::Display for NativeBackendError {
77    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
78        match &self.source {
79            NativeBackendErrorSource::Decode(source) => source.fmt(f),
80            NativeBackendErrorSource::Encode(source) => source.fmt(f),
81        }
82    }
83}
84
85#[cfg(not(any(test, target_os = "macos")))]
86impl core::fmt::Display for NativeBackendError {
87    fn fmt(&self, _formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        match self.source {}
89    }
90}
91
92#[cfg(any(test, target_os = "macos"))]
93impl core::error::Error for NativeBackendError {
94    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
95        Some(match &self.source {
96            NativeBackendErrorSource::Decode(source) => source,
97            NativeBackendErrorSource::Encode(source) => source,
98        })
99    }
100}
101
102#[cfg(not(any(test, target_os = "macos")))]
103impl core::error::Error for NativeBackendError {}