use std::fmt;
pub type Result<T> = std::result::Result<T, InchiError>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Status {
Okay,
Warning,
Error,
Fatal,
Unknown,
Busy,
Eof,
Other(i32),
}
impl Status {
#[must_use]
pub fn from_code(code: i32) -> Self {
match code {
0 => Status::Okay,
1 => Status::Warning,
2 => Status::Error,
3 => Status::Fatal,
4 => Status::Unknown,
5 => Status::Busy,
-1 => Status::Eof,
other => Status::Other(other),
}
}
#[must_use]
pub fn is_success(self) -> bool {
matches!(self, Status::Okay | Status::Warning)
}
}
impl fmt::Display for Status {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Status::Okay => "okay",
Status::Warning => "warning",
Status::Error => "error",
Status::Fatal => "fatal error",
Status::Unknown => "unknown error",
Status::Busy => "busy",
Status::Eof => "no input",
Status::Other(code) => return write!(f, "unrecognized status {code}"),
};
f.write_str(s)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum InchiError {
Failed {
status: Status,
message: String,
},
EmptyResult,
InteriorNul {
position: usize,
},
InvalidStructure {
reason: String,
},
}
impl InchiError {
#[must_use]
pub fn status(&self) -> Option<Status> {
match self {
InchiError::Failed { status, .. } => Some(*status),
_ => None,
}
}
}
impl fmt::Display for InchiError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InchiError::Failed { status, message } if message.is_empty() => {
write!(f, "InChI generation failed: {status}")
}
InchiError::Failed { status, message } => {
write!(f, "InChI generation failed: {status}: {message}")
}
InchiError::EmptyResult => {
f.write_str("the InChI library produced an empty result")
}
InchiError::InteriorNul { position } => {
write!(f, "input contains an interior NUL byte at position {position}")
}
InchiError::InvalidStructure { reason } => {
write!(f, "invalid structure: {reason}")
}
}
}
}
impl std::error::Error for InchiError {}