use std::{
ffi::{CStr, NulError},
fmt,
};
use num_enum::FromPrimitive;
use thiserror::Error;
use crate::ffi::CXmpError;
#[derive(Debug, Eq, PartialEq)]
#[non_exhaustive]
pub struct XmpError {
pub error_type: XmpErrorType,
pub debug_message: String,
}
impl XmpError {
pub(crate) fn raise_from_c(err: &CXmpError) -> XmpResult<()> {
if err.had_error != 0 {
Err(XmpError {
error_type: XmpErrorType::from(err.id),
debug_message: if err.debug_message.is_null() {
String::default()
} else {
unsafe {
CStr::from_ptr(err.debug_message)
.to_string_lossy()
.into_owned()
}
},
})
} else {
Ok(())
}
}
}
impl From<NulError> for XmpError {
fn from(_: NulError) -> Self {
XmpError {
error_type: XmpErrorType::NulInRustString,
debug_message: "Unable to convert to C string because a NUL byte was found".to_owned(),
}
}
}
impl fmt::Display for XmpError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
if self.debug_message.is_empty() {
write!(f, "XmpError({})", self.error_type)
} else {
write!(f, "XmpError({}, {})", self.error_type, self.debug_message)
}
}
}
impl std::error::Error for XmpError {}
#[derive(Debug, Eq, Error, FromPrimitive, PartialEq)]
#[non_exhaustive]
#[repr(i32)]
pub enum XmpErrorType {
#[error("Unknown error")]
#[default]
Unknown = 0,
#[error("Undefined error")]
Tbd = 1,
#[error("Unavailable error")]
Unavailable = 2,
#[error("Bad object")]
BadObject = 3,
#[error("Bad parameter")]
BadParam = 4,
#[error("Bad value")]
BadValue = 5,
#[error("Assertion failure")]
AssertFailure = 6,
#[error("Enforcement failure")]
EnforceFailure = 7,
#[error("Unimplemented")]
Unimplemented = 8,
#[error("Internal failure")]
InternalFailure = 9,
#[error("Deprecated")]
Deprecated = 10,
#[error("External failure")]
ExternalFailure = 11,
#[error("User abort")]
UserAbort = 12,
#[error("Standard exception")]
StdException = 13,
#[error("Unknown exception")]
UnknownException = 14,
#[error("Out of memory")]
NoMemory = 15,
#[error("Progress callback requested abort")]
ProgressAbort = 16,
#[error("Bad schema")]
BadSchema = 101,
#[error("Bad XPath")]
BadXPath = 102,
#[error("Bad options parameter")]
BadOptions = 103,
#[error("Bad index parameter")]
BadIndex = 104,
#[error("Bad iteration position")]
BadIterPosition = 105,
#[error("XML parsing error")]
BadParse = 106,
#[error("Serialization error")]
BadSerialize = 107,
#[error("File format error")]
BadFileFormat = 108,
#[error("No file handler found for format")]
NoFileHandler = 109,
#[error("Data too large for JPEG file format")]
TooLargeForJpeg = 110,
#[error("File not found")]
NoFile = 111,
#[error("File permission error")]
FilePermission = 112,
#[error("Out of disk space")]
DiskSpace = 113,
#[error("Unable to read file")]
ReadError = 114,
#[error("Unable to write file")]
WriteError = 115,
#[error("File format error")]
BadBlockFormat = 116,
#[error("Path does not point to a file")]
FilePathNotAFile = 117,
#[error("Rejected file extension")]
RejectedFileExtension = 118,
#[error("XML format error")]
BadXml = 201,
#[error("RDF format error")]
BadRdf = 202,
#[error("XMP format error")]
BadXmp = 203,
#[error("Empty iterator")]
EmptyIterator = 204,
#[error("Unicode error")]
BadUnicode = 205,
#[error("TIFF format error")]
BadTiff = 206,
#[error("JPEG format error")]
BadJpeg = 207,
#[error("PSD format error")]
BadPsd = 208,
#[error("PSIR format error")]
BadPsir = 209,
#[error("IPTC format error")]
BadIptc = 210,
#[error("MPEG format error")]
BadMpeg = 211,
#[error("HEIF construction method not supported")]
HeifConstructionMethodNotSupported = 212,
#[error("PNG format error")]
BadPng = 213,
#[error("Unable to convert to C string because a NUL byte was found")]
NulInRustString = -432,
#[error("C++ XMP toolkit did not initialize properly")]
NoCppToolkit = -433,
#[error("x:xmpmeta element not found")]
XmpMetaElementMissing = -434,
}
pub type XmpResult<T> = std::result::Result<T, XmpError>;