use std::error::Error as StdError;
use std::ffi::CStr;
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use libsamplerate_rs::src_strerror;
#[non_exhaustive]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ErrorKind {
Unknown = -1,
MallocFailed = 1,
BadState = 2,
BadData = 3,
BadDataPtr = 4,
NoPrivate = 5,
BadSrcRatio = 6,
BadProcPtr = 7,
ShiftBits = 8,
FilterLen = 9,
BadConverter = 10,
BadChannelCount = 11,
SincBadBufferLen = 12,
SizeIncompatibility = 13,
BadPrivPtr = 14,
BadSincState = 15,
DataOverlap = 16,
BadCallback = 17,
BadMode = 18,
NullCallback = 19,
NoVariableRatio = 20,
SincPrepareDataBadLen = 21,
BadInternalState = 22,
MaxError = 23,
}
impl ErrorKind {
pub(crate) fn from_int(value: i32) -> Option<Self> {
let slf = match value {
0 => return None,
1 => Self::MallocFailed,
2 => Self::BadState,
3 => Self::BadData,
4 => Self::BadDataPtr,
5 => Self::NoPrivate,
6 => Self::BadSrcRatio,
7 => Self::BadProcPtr,
8 => Self::ShiftBits,
9 => Self::FilterLen,
10 => Self::BadConverter,
11 => Self::BadChannelCount,
12 => Self::SincBadBufferLen,
13 => Self::SizeIncompatibility,
14 => Self::BadPrivPtr,
15 => Self::BadSincState,
16 => Self::DataOverlap,
17 => Self::BadCallback,
18 => Self::BadMode,
19 => Self::NullCallback,
20 => Self::NoVariableRatio,
21 => Self::SincPrepareDataBadLen,
22 => Self::BadInternalState,
23 => Self::MaxError,
_ => Self::Unknown,
};
Some(slf)
}
pub fn description(&self) -> &'static str {
match self {
Self::Unknown => "Unkown error.",
_ => {
let ptr = unsafe { src_strerror(*self as i32) };
assert!(!ptr.is_null());
unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
},
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct Error {
kind: ErrorKind,
}
impl Error {
pub(crate) fn check_int(error: i32) -> Result<(), Self> {
match ErrorKind::from_int(error) {
None => Ok(()),
Some(kind) => Err(Self::from(kind)),
}
}
#[inline]
pub fn kind(&self) -> ErrorKind {
self.kind
}
#[inline]
pub fn description(&self) -> &'static str {
self.kind.description()
}
}
impl From<ErrorKind> for Error {
#[inline]
fn from(kind: ErrorKind) -> Self {
Self { kind }
}
}
impl Display for Error {
#[inline]
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(f, "{}", self.description())
}
}
impl StdError for Error {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create_converter_type_from_int() {
assert_eq!(ErrorKind::from_int(0), None);
assert_eq!(ErrorKind::from_int(1), Some(ErrorKind::MallocFailed));
assert_eq!(ErrorKind::from_int(2), Some(ErrorKind::BadState));
assert_eq!(ErrorKind::from_int(3), Some(ErrorKind::BadData));
assert_eq!(ErrorKind::from_int(4), Some(ErrorKind::BadDataPtr));
assert_eq!(ErrorKind::from_int(5), Some(ErrorKind::NoPrivate));
assert_eq!(ErrorKind::from_int(6), Some(ErrorKind::BadSrcRatio));
assert_eq!(ErrorKind::from_int(7), Some(ErrorKind::BadProcPtr));
assert_eq!(ErrorKind::from_int(8), Some(ErrorKind::ShiftBits));
assert_eq!(ErrorKind::from_int(9), Some(ErrorKind::FilterLen));
assert_eq!(ErrorKind::from_int(10), Some(ErrorKind::BadConverter));
assert_eq!(ErrorKind::from_int(11), Some(ErrorKind::BadChannelCount));
assert_eq!(ErrorKind::from_int(12), Some(ErrorKind::SincBadBufferLen));
assert_eq!(
ErrorKind::from_int(13),
Some(ErrorKind::SizeIncompatibility)
);
assert_eq!(ErrorKind::from_int(14), Some(ErrorKind::BadPrivPtr));
assert_eq!(ErrorKind::from_int(15), Some(ErrorKind::BadSincState));
assert_eq!(ErrorKind::from_int(16), Some(ErrorKind::DataOverlap));
assert_eq!(ErrorKind::from_int(17), Some(ErrorKind::BadCallback));
assert_eq!(ErrorKind::from_int(18), Some(ErrorKind::BadMode));
assert_eq!(ErrorKind::from_int(19), Some(ErrorKind::NullCallback));
assert_eq!(ErrorKind::from_int(20), Some(ErrorKind::NoVariableRatio));
assert_eq!(
ErrorKind::from_int(21),
Some(ErrorKind::SincPrepareDataBadLen)
);
assert_eq!(ErrorKind::from_int(22), Some(ErrorKind::BadInternalState));
assert_eq!(ErrorKind::from_int(23), Some(ErrorKind::MaxError));
assert_eq!(ErrorKind::from_int(24), Some(ErrorKind::Unknown));
}
#[test]
fn description() {
assert_eq!(ErrorKind::MallocFailed.description(), "Malloc failed.");
assert_eq!(
ErrorKind::BadState.description(),
"SRC_STATE pointer is NULL."
);
assert_eq!(
ErrorKind::BadData.description(),
"SRC_DATA pointer is NULL."
);
assert_eq!(
ErrorKind::BadDataPtr.description(),
"SRC_DATA->data_out or SRC_DATA->data_in is NULL."
);
assert_eq!(
ErrorKind::NoPrivate.description(),
"Internal error. No private data."
);
assert_eq!(
ErrorKind::BadSrcRatio.description(),
"SRC ratio outside [1/256, 256] range."
);
assert_eq!(
ErrorKind::BadSincState.description(),
"src_process() called without reset after end_of_input."
);
assert_eq!(
ErrorKind::BadProcPtr.description(),
"Internal error. No process pointer."
);
assert_eq!(
ErrorKind::ShiftBits.description(),
"Internal error. SHIFT_BITS too large."
);
assert_eq!(
ErrorKind::FilterLen.description(),
"Internal error. Filter length too large."
);
assert_eq!(
ErrorKind::BadConverter.description(),
"Bad converter number."
);
assert_eq!(
ErrorKind::BadChannelCount.description(),
"Channel count must be >= 1."
);
assert_eq!(
ErrorKind::SincBadBufferLen.description(),
"Internal error. Bad buffer length. Please report this."
);
assert_eq!(
ErrorKind::SizeIncompatibility.description(),
"Internal error. Input data / internal buffer size difference. Please report this."
);
assert_eq!(
ErrorKind::BadPrivPtr.description(),
"Internal error. Private pointer is NULL. Please report this."
);
assert_eq!(
ErrorKind::DataOverlap.description(),
"Input and output data arrays overlap."
);
assert_eq!(
ErrorKind::BadCallback.description(),
"Supplied callback function pointer is NULL."
);
assert_eq!(
ErrorKind::BadMode.description(),
"Calling mode differs from initialisation mode (ie process v callback)."
);
assert_eq!(
ErrorKind::NullCallback.description(),
"Callback function pointer is NULL in src_callback_read ()."
);
assert_eq!(
ErrorKind::NoVariableRatio.description(),
"This converter only allows constant conversion ratios."
);
assert_eq!(
ErrorKind::SincPrepareDataBadLen.description(),
"Internal error : Bad length in prepare_data ()."
);
assert_eq!(
ErrorKind::BadInternalState.description(),
"Error : Someone is trampling on my internal state."
);
assert_eq!(
ErrorKind::MaxError.description(),
"Placeholder. No error defined for this error number."
);
assert_eq!(ErrorKind::Unknown.description(), "Unkown error.");
}
}