Skip to main content

nvtiff_sys/
result.rs

1//! A thin wrapper around [`nvtiffStatus_t`] providing [Result]s with [`NvTiffError`].
2#![warn(missing_docs)]
3use thiserror::Error;
4
5use crate::nvtiffStatus_t;
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
68    /// A custom (or unimplemented) error that does not fall under any other nvTIFF
69    /// status error kind.
70    #[error("Unknown nvTiff error with status code {0}")]
71    Other(u32),
72}
73
74/// Trait for checking nvTIFF API return status codes
75pub trait NvTiffResultCheck {
76    /// Check if the nvTIFF API call has finished successfully.
77    ///
78    /// # Errors
79    /// Will return [`NvTiffError`] if the status code is non-zero.
80    fn result(self) -> NvTiffResult<()>;
81}
82
83impl NvTiffResultCheck for nvtiffStatus_t::Type {
84    /// Check if the nvTIFF Decode API call has finished successfully. Note that many of
85    /// the calls are asynchronous and some of the errors may be seen only after
86    /// synchronization.
87    ///
88    /// # Errors
89    /// Will return [`NvTiffError::StatusError`] if the status code is non-zero.
90    fn result(self) -> NvTiffResult<()> {
91        match self {
92            nvtiffStatus_t::NVTIFF_STATUS_SUCCESS => Ok(()),
93            nvtiffStatus_t::NVTIFF_STATUS_NOT_INITIALIZED => {
94                Err(NvTiffError::StatusError(NvTiffStatusError::NotInitialized))
95            }
96            nvtiffStatus_t::NVTIFF_STATUS_INVALID_PARAMETER => Err(NvTiffError::StatusError(
97                NvTiffStatusError::InvalidParameter,
98            )),
99            nvtiffStatus_t::NVTIFF_STATUS_BAD_TIFF => {
100                Err(NvTiffError::StatusError(NvTiffStatusError::BadTiff))
101            }
102            nvtiffStatus_t::NVTIFF_STATUS_TIFF_NOT_SUPPORTED => Err(NvTiffError::StatusError(
103                NvTiffStatusError::TiffNotSupported,
104            )),
105            nvtiffStatus_t::NVTIFF_STATUS_ALLOCATOR_FAILURE => Err(NvTiffError::StatusError(
106                NvTiffStatusError::AllocatorFailure,
107            )),
108            nvtiffStatus_t::NVTIFF_STATUS_EXECUTION_FAILED => {
109                Err(NvTiffError::StatusError(NvTiffStatusError::ExecutionFailed))
110            }
111            nvtiffStatus_t::NVTIFF_STATUS_ARCH_MISMATCH => {
112                Err(NvTiffError::StatusError(NvTiffStatusError::ArchMismatch))
113            }
114            nvtiffStatus_t::NVTIFF_STATUS_INTERNAL_ERROR => {
115                Err(NvTiffError::StatusError(NvTiffStatusError::InternalError))
116            }
117            nvtiffStatus_t::NVTIFF_STATUS_NVCOMP_NOT_FOUND => {
118                Err(NvTiffError::StatusError(NvTiffStatusError::NvcompNotFound))
119            }
120            nvtiffStatus_t::NVTIFF_STATUS_NVJPEG_NOT_FOUND => {
121                Err(NvTiffError::StatusError(NvTiffStatusError::NvjpegNotFound))
122            }
123            nvtiffStatus_t::NVTIFF_STATUS_TAG_NOT_FOUND => {
124                Err(NvTiffError::StatusError(NvTiffStatusError::TagNotFound))
125            }
126            nvtiffStatus_t::NVTIFF_STATUS_PARAMETER_OUT_OF_BOUNDS => Err(NvTiffError::StatusError(
127                NvTiffStatusError::ParameterOutOfBounds,
128            )),
129            nvtiffStatus_t::NVTIFF_STATUS_NVJPEG2K_NOT_FOUND => Err(NvTiffError::StatusError(
130                NvTiffStatusError::Nvjpeg2kNotFound,
131            )),
132            // Unknown nvTIFF decode API status code
133            status_code => Err(NvTiffError::StatusError(NvTiffStatusError::Other(
134                status_code,
135            ))),
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use std::ffi::CString;
143
144    use crate::{
145        NvTiffResultCheck, nvtiffStatus_t, nvtiffStream, nvtiffStreamCreate,
146        nvtiffStreamGetNumImages, nvtiffStreamParseFromFile,
147    };
148
149    #[test]
150    fn test_nvtiff_status_result() {
151        let mut stream = std::mem::MaybeUninit::uninit();
152        let mut tiff_stream: *mut nvtiffStream = stream.as_mut_ptr();
153
154        // Check return code = 0 success
155        let status_create: nvtiffStatus_t::Type =
156            unsafe { nvtiffStreamCreate(&raw mut tiff_stream) };
157        dbg!(status_create); // should be 0=SUCCESS
158        assert!(status_create.result().is_ok());
159
160        let tiff_cstr = CString::new("images/invalid.tif").unwrap();
161        let tiff_path: *const std::os::raw::c_char = tiff_cstr.as_ptr();
162
163        // Check return code >= 1 failure
164        let status_parse: nvtiffStatus_t::Type =
165            unsafe { nvtiffStreamParseFromFile(tiff_path, tiff_stream) };
166        dbg!(status_parse); // should be 2=NVTIFF_STATUS_INVALID_PARAMETER
167        assert!(status_parse.result().is_err());
168    }
169
170    #[test]
171    fn test_nvtiff_other_error() {
172        let status_unknown: nvtiffStatus_t::Type = 42; // mock unimplemented status code
173        dbg!(status_unknown); // should be 42=?
174        assert!(status_unknown.result().is_err());
175    }
176
177    #[test]
178    fn nvtiff_status_to_string() {
179        let mut host_stream = std::mem::MaybeUninit::uninit();
180        let tiff_stream: *mut nvtiffStream = host_stream.as_mut_ptr();
181
182        // Set up empty tiff stream
183        let mut num_images: u32 = 0;
184        let status_numimages: u32 =
185            unsafe { nvtiffStreamGetNumImages(tiff_stream, &raw mut num_images) };
186        dbg!(status_numimages);
187
188        // Check that errors can be turned into string form
189        assert_eq!(
190            status_numimages.result().unwrap_err().to_string(),
191            "Status error: Wrong parameter was passed.".to_string()
192        );
193    }
194}