use std::error;
use std::ffi::{c_int, c_long, CStr};
use std::fmt;
use num_traits::cast::AsPrimitive;
use crate::{raw, MSErrorCode, MSResult};
const MS_NOERROR: c_long = raw::MS_NOERROR as c_long;
const MS_ENDOFFILE: c_long = raw::MS_ENDOFFILE as c_long;
const MS_NSTERROR: i64 = raw::NSTERROR as i64;
pub(crate) fn check<T: PartialOrd + AsPrimitive<c_long>>(code: T) -> MSResult<T> {
let c = code.as_();
if c >= MS_NOERROR {
return Ok(code);
}
Err(MSError::from_raw(c as c_int))
}
pub(crate) fn check_eof<T: PartialEq + AsPrimitive<c_long>>(code: T) -> bool {
code.as_() == MS_ENDOFFILE
}
pub(crate) fn check_nst(code: i64) -> MSResult<i64> {
if code > MS_NSTERROR {
return Ok(code);
}
Err(MSError::from_str("time processing error"))
}
#[derive(Debug, PartialEq)]
pub struct MSError {
code: c_int,
message: String,
}
pub(crate) const MS_GENERROR: c_int = raw::MS_GENERROR as c_int;
pub(crate) const MS_NOTSEED: c_int = raw::MS_NOTSEED as c_int;
pub(crate) const MS_WRONGLENGTH: c_int = raw::MS_WRONGLENGTH as c_int;
pub(crate) const MS_OUTOFRANGE: c_int = raw::MS_OUTOFRANGE as c_int;
pub(crate) const MS_UNKNOWNFORMAT: c_int = raw::MS_UNKNOWNFORMAT as c_int;
pub(crate) const MS_STBADCOMPFLAG: c_int = raw::MS_STBADCOMPFLAG as c_int;
pub(crate) const MS_INVALIDCRC: c_int = raw::MS_INVALIDCRC as c_int;
impl MSError {
pub(crate) fn from_raw(code: c_int) -> Self {
unsafe {
let message = CStr::from_ptr(raw::ms_errorstr(code)).to_bytes();
let message = String::from_utf8_lossy(message).into_owned();
Self { code, message }
}
}
pub fn from_str(s: &str) -> Self {
Self {
code: MS_GENERROR,
message: s.to_string(),
}
}
pub fn code(&self) -> MSErrorCode {
match self.raw_code() {
MS_NOTSEED => MSErrorCode::NotSEED,
MS_WRONGLENGTH => MSErrorCode::WrongLength,
MS_OUTOFRANGE => MSErrorCode::OutOfRange,
MS_UNKNOWNFORMAT => MSErrorCode::UnknownFormat,
MS_STBADCOMPFLAG => MSErrorCode::SteimBadCompressionFlag,
MS_INVALIDCRC => MSErrorCode::InvalidCRC,
_ => MSErrorCode::GenericError,
}
}
pub fn raw_code(&self) -> c_int {
match self.code {
MS_NOTSEED => MS_NOTSEED,
MS_WRONGLENGTH => MS_WRONGLENGTH,
MS_OUTOFRANGE => MS_OUTOFRANGE,
MS_UNKNOWNFORMAT => MS_UNKNOWNFORMAT,
MS_STBADCOMPFLAG => MS_STBADCOMPFLAG,
MS_INVALIDCRC => MS_INVALIDCRC,
_ => MS_GENERROR,
}
}
pub fn message(&self) -> &str {
&self.message
}
}
impl error::Error for MSError {}
impl fmt::Display for MSError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}; code={:?} ({})",
self.message,
self.code(),
self.code
)?;
Ok(())
}
}