Skip to main content

nvtiff_sys/
result.rs

1//! A thin wrapper around [`nvtiffStatus`] providing [Result]s with [`NvTiffError`].
2#![warn(missing_docs)]
3use thiserror::Error;
4
5use crate::nvtiffStatus;
6
7/// Result of an nvTIFF API call
8pub type NvTiffResult<T> = Result<T, NvTiffError>;
9
10/// Errors from an nvTIFF API call
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum NvTiffError {
14    /// An error occured while decoding the TIFF image.
15    #[error("Status error: {0}")]
16    StatusError(NvTiffStatusError),
17}
18
19/// nvTIFF Decode API non-zero return status codes
20///
21/// Based on
22/// <https://docs.nvidia.com/cuda/nvtiff/userguide.html#decode-api-return-status-codes>
23#[derive(Debug, Eq, Error, PartialEq)]
24#[non_exhaustive]
25pub enum NvTiffStatusError {
26    /// The library handle was not initialized.
27    #[error("The library handle was not initialized.")]
28    NotInitialized, // 1
29    /// Wrong parameter was passed. For example, a null pointer as input data, or an
30    /// invalid enum value.
31    #[error("Wrong parameter was passed.")]
32    InvalidParameter, // 2
33    /// Cannot parse the TIFF stream. Likely due to a corruption that cannot be handled.
34    #[error("Cannot parse the TIFF stream.")]
35    BadTiff, // 3
36    /// Attempting to decode a TIFF stream that is not supported by the nvTIFF library.
37    #[error("Attempting to decode a TIFF stream that is not supported by the nvTIFF library.")]
38    TiffNotSupported, // 4
39    /// The user-provided allocator functions, for either memory allocation or for
40    /// releasing the memory, returned a non-zero code.
41    #[error("The user-provided allocator functions returned a non-zero code.")]
42    AllocatorFailure, // 5
43    /// Error during the execution of the device tasks.
44    #[error("Error during the execution of the device tasks.")]
45    ExecutionFailed, // 6
46    /// The device capabilities are not enough for the set of input parameters provided.
47    #[error("The device capabilities are not enough for the set of input parameters provided.")]
48    ArchMismatch, // 7
49    /// Unknown error occured in the library.
50    #[error("Unknown error occured in the library.")]
51    InternalError, // 8
52    /// nvTiff is unable to load the nvcomp library.
53    #[error("nvTiff is unable to load the nvCOMP library.")]
54    NvcompNotFound, // 9
55    /// nvTiff is unable to load the nvjpeg library.
56    #[error("nvTiff is unable to load the nvJPEG library.")]
57    NvjpegNotFound, // 10
58    /// nvTiff is unable to find information about the provided tag.
59    #[error("nvTiff is unable to find information about the provided tag.")]
60    TagNotFound, // 11
61    /// Provided parameter is outside the range of possible values.
62    #[error("Provided parameter is outside the range of possible values.")]
63    ParameterOutOfBounds, // 12
64    /// nvTiff is unable to load the nvJPEG2000 library.
65    #[error("nvTiff is unable to load the nvJPEG2000 library.")]
66    Nvjpeg2kNotFound, // 13
67    /// Each region in a multi-region decode request is individually decodable, but the
68    /// requested regions cannot execute as one compatible batch under the current
69    /// batching rules. Distinct from invalid-parameter and single-image
70    /// unsupported-image errors.
71    #[error(
72        "Requested regions cannot execute as one compatible batch under the current batching rules."
73    )]
74    BatchIncompatible,
75
76    /// A custom (or unimplemented) error that does not fall under any other nvTIFF
77    /// status error kind.
78    #[error("Unknown nvTiff error with status code {0}")]
79    Other(u32),
80}
81
82/// Trait for checking nvTIFF API return status codes
83pub trait NvTiffResultCheck {
84    /// Check if the nvTIFF API call has finished successfully.
85    ///
86    /// # Errors
87    /// Will return [`NvTiffError`] if the status code is non-zero.
88    fn result(self) -> NvTiffResult<()>;
89}
90
91impl NvTiffResultCheck for nvtiffStatus::Type {
92    /// Check if the nvTIFF Decode API call has finished successfully. Note that many of
93    /// the calls are asynchronous and some of the errors may be seen only after
94    /// synchronization.
95    ///
96    /// # Errors
97    /// Will return [`NvTiffError::StatusError`] if the status code is non-zero.
98    fn result(self) -> NvTiffResult<()> {
99        match self {
100            nvtiffStatus::NVTIFF_STATUS_SUCCESS => Ok(()),
101            nvtiffStatus::NVTIFF_STATUS_NOT_INITIALIZED => {
102                Err(NvTiffError::StatusError(NvTiffStatusError::NotInitialized))
103            }
104            nvtiffStatus::NVTIFF_STATUS_INVALID_PARAMETER => Err(NvTiffError::StatusError(
105                NvTiffStatusError::InvalidParameter,
106            )),
107            nvtiffStatus::NVTIFF_STATUS_BAD_TIFF => {
108                Err(NvTiffError::StatusError(NvTiffStatusError::BadTiff))
109            }
110            nvtiffStatus::NVTIFF_STATUS_TIFF_NOT_SUPPORTED => Err(NvTiffError::StatusError(
111                NvTiffStatusError::TiffNotSupported,
112            )),
113            nvtiffStatus::NVTIFF_STATUS_ALLOCATOR_FAILURE => Err(NvTiffError::StatusError(
114                NvTiffStatusError::AllocatorFailure,
115            )),
116            nvtiffStatus::NVTIFF_STATUS_EXECUTION_FAILED => {
117                Err(NvTiffError::StatusError(NvTiffStatusError::ExecutionFailed))
118            }
119            nvtiffStatus::NVTIFF_STATUS_ARCH_MISMATCH => {
120                Err(NvTiffError::StatusError(NvTiffStatusError::ArchMismatch))
121            }
122            nvtiffStatus::NVTIFF_STATUS_INTERNAL_ERROR => {
123                Err(NvTiffError::StatusError(NvTiffStatusError::InternalError))
124            }
125            nvtiffStatus::NVTIFF_STATUS_NVCOMP_NOT_FOUND => {
126                Err(NvTiffError::StatusError(NvTiffStatusError::NvcompNotFound))
127            }
128            nvtiffStatus::NVTIFF_STATUS_NVJPEG_NOT_FOUND => {
129                Err(NvTiffError::StatusError(NvTiffStatusError::NvjpegNotFound))
130            }
131            nvtiffStatus::NVTIFF_STATUS_TAG_NOT_FOUND => {
132                Err(NvTiffError::StatusError(NvTiffStatusError::TagNotFound))
133            }
134            nvtiffStatus::NVTIFF_STATUS_PARAMETER_OUT_OF_BOUNDS => Err(NvTiffError::StatusError(
135                NvTiffStatusError::ParameterOutOfBounds,
136            )),
137            nvtiffStatus::NVTIFF_STATUS_NVJPEG2K_NOT_FOUND => Err(NvTiffError::StatusError(
138                NvTiffStatusError::Nvjpeg2kNotFound,
139            )),
140            nvtiffStatus::NVTIFF_STATUS_BATCH_INCOMPATIBLE => Err(NvTiffError::StatusError(
141                NvTiffStatusError::BatchIncompatible,
142            )),
143            // Unknown nvTIFF decode API status code
144            status_code => Err(NvTiffError::StatusError(NvTiffStatusError::Other(
145                status_code,
146            ))),
147        }
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use std::ffi::CString;
154
155    use crate::{
156        NvTiffResultCheck, nvtiffStatus, nvtiffStream, nvtiffStreamGetNextIFDOffset,
157        nvtiffStreamOpenFromFile,
158    };
159
160    #[test]
161    fn nvtiff_status_result() {
162        let mut stream = std::mem::MaybeUninit::uninit();
163        let mut tiff_stream: *mut nvtiffStream = stream.as_mut_ptr();
164
165        let tiff_cstr = CString::new("images/float32.tif").unwrap();
166        let tiff_path: *const std::os::raw::c_char = tiff_cstr.as_ptr();
167
168        // Check return code = 0 success
169        let status_create: nvtiffStatus::Type =
170            unsafe { nvtiffStreamOpenFromFile(tiff_path, &raw mut tiff_stream) };
171        dbg!(status_create); // should be 0=SUCCESS
172        assert!(status_create.result().is_ok());
173
174        let tiff_cstr = CString::new("images/invalid.tif").unwrap();
175        let tiff_path: *const std::os::raw::c_char = tiff_cstr.as_ptr();
176
177        // Check return code >= 1 failure
178        let status_parse: nvtiffStatus::Type =
179            unsafe { nvtiffStreamOpenFromFile(tiff_path, &raw mut tiff_stream) };
180        dbg!(status_parse); // should be 2=NVTIFF_STATUS_INVALID_PARAMETER
181        assert!(status_parse.result().is_err());
182    }
183
184    #[test]
185    fn nvtiff_other_error() {
186        let status_unknown: nvtiffStatus::Type = 42; // mock unimplemented status code
187        dbg!(status_unknown); // should be 42=?
188        assert!(status_unknown.result().is_err());
189    }
190
191    #[test]
192    fn status_to_string() {
193        let mut host_stream = std::mem::MaybeUninit::uninit();
194        let tiff_stream: *mut nvtiffStream = host_stream.as_mut_ptr();
195
196        // Set up empty tiff stream
197        let mut ifd_offset: usize = 0;
198        let status_nextifdoffset: u32 =
199            unsafe { nvtiffStreamGetNextIFDOffset(tiff_stream, ifd_offset, &raw mut ifd_offset) };
200        dbg!(status_nextifdoffset);
201
202        // Check that errors can be turned into string form
203        assert_eq!(
204            status_nextifdoffset.result().unwrap_err().to_string(),
205            "Status error: Wrong parameter was passed.".to_string()
206        );
207    }
208}