use crate::types::*;
use serde::ser::SerializeStruct;
use serde::Serialize;
use std::fmt;
#[derive(Debug)]
pub enum StamError {
HandleError(&'static str),
IdNotFoundError(String, &'static str),
NotFoundError(Type, String),
VariableNotFoundError(String, Option<Type>, &'static str),
NoIdError(&'static str),
Unbound(&'static str),
AlreadyBound(&'static str),
AlreadyExists(usize, &'static str),
DuplicateIdError(String, &'static str),
BuildError(Box<StamError>, &'static str),
StoreError(Box<StamError>, &'static str),
IOError(std::io::Error, String, &'static str),
JsonError(
serde_path_to_error::Error<serde_json::error::Error>,
String, &'static str,
),
#[cfg(feature = "csv")]
CsvError(String, &'static str),
RegexError(regex::Error, &'static str),
QuerySyntaxError(String, &'static str),
SerializationError(String),
DeserializationError(String),
WrongSelectorType(&'static str),
WrongSelectorTarget(&'static str),
CursorOutOfBounds(Cursor, &'static str),
InvalidOffset(Cursor, Cursor, &'static str),
InvalidCursor(String, &'static str),
NoTarget(&'static str),
NoText(&'static str),
InUse(&'static str),
IncompleteError(String, &'static str),
ValueError(String, &'static str),
UndefinedVariable(String, &'static str),
#[cfg(feature = "translate")]
TranslateError(String, &'static str),
#[cfg(feature = "transpose")]
TransposeError(String, &'static str),
ValidationError(String, &'static str),
OtherError(&'static str),
}
impl StamError {
pub fn name(&self) -> &'static str {
match self {
StamError::HandleError(..) => "HandleError",
StamError::IdNotFoundError(..) => "IdNotFoundError",
StamError::NotFoundError(..) => "NotFoundError",
StamError::Unbound(..) => "Unbound",
StamError::AlreadyBound(..) => "AlreadyBound",
StamError::AlreadyExists(..) => "AlreadyExists",
StamError::NoIdError(..) => "NoIdError",
StamError::DuplicateIdError(..) => "DuplicateIdError",
StamError::IOError(..) => "IoError",
StamError::JsonError(..) => "JsonError",
#[cfg(feature = "csv")]
StamError::CsvError(..) => "CsvError",
StamError::RegexError(..) => "RegexError",
StamError::QuerySyntaxError(..) => "QuerySyntaxError",
StamError::SerializationError(..) => "SerializationError",
StamError::DeserializationError(..) => "DeserializationError",
StamError::BuildError(..) => "BuildError",
StamError::StoreError(..) => "StoreError",
StamError::WrongSelectorType(..) => "WrongSelectorType",
StamError::WrongSelectorTarget(..) => "WrongSelectorTarget",
StamError::CursorOutOfBounds(..) => "CursorOutOfBounds",
StamError::InvalidOffset(..) => "InvalidOffset",
StamError::InvalidCursor(..) => "InvalidCursor",
StamError::NoTarget(..) => "NoTarget",
StamError::NoText(..) => "NoText",
StamError::InUse(..) => "InUse",
StamError::IncompleteError(..) => "IncompleteError",
StamError::ValueError(..) => "ValueError",
#[cfg(feature = "transpose")]
StamError::TransposeError(..) => "TransposeError",
StamError::TranslateError(..) => "TranslateError",
StamError::ValidationError(..) => "ValidationError",
StamError::UndefinedVariable(..) => "UndefinedVariable",
StamError::VariableNotFoundError(..) => "VariableNotFoundError",
StamError::OtherError(..) => "OtherError",
}
}
}
impl Serialize for StamError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_struct("StamError", 3)?;
let message: String = self.into();
state.serialize_field("@type", "StamError")?;
state.serialize_field("name", self.name())?;
state.serialize_field("message", &message)?;
state.end()
}
}
impl From<&StamError> for String {
fn from(error: &StamError) -> String {
match error {
StamError::HandleError(contextmsg) => {
format!("IntIdError: No such internal ID: ({})", contextmsg)
}
StamError::IdNotFoundError(id, contextmsg) => {
format!("IdError: No such ID: {} ({})", id, contextmsg)
}
StamError::NotFoundError(tp, msg) => {
format!("NotFoundError: {} not found: {}", tp, msg)
}
StamError::Unbound(contextmsg) => format!(
"Unbound: Item is not bound yet, add it to a store first. ({})",
contextmsg
),
StamError::AlreadyBound(contextmsg) => {
format!("AlreadyBound: Item is already bound. ({})", contextmsg)
}
StamError::AlreadyExists(intid, contextmsg) => format!(
"AlreadyExists: Item already exists: {} ({})",
intid, contextmsg
),
StamError::NoIdError(contextmsg) => {
format!("NoIdError: Store does not map IDs. ({})", contextmsg)
}
StamError::DuplicateIdError(id, contextmsg) => format!(
"DuplicateIdError: ID already exists for a different item: {} ({})",
id, contextmsg
),
StamError::IOError(err, filename, contextmsg) => {
format!("IOError for {}: {} ({})", filename, err, contextmsg)
}
StamError::JsonError(err, input, contextmsg) => {
format!(
"JsonError: Parsing failed: {} ({}). Input: {}",
err, contextmsg, input
)
}
#[cfg(feature = "csv")]
StamError::CsvError(msg, contextmsg) => {
format!("CsvError: Parsing failed: {} ({})", msg, contextmsg)
}
StamError::RegexError(err, contextmsg) => {
format!("RegexError: {} ({})", err, contextmsg)
}
StamError::QuerySyntaxError(err, contextmsg) => {
format!(
"QuerySyntaxError: Malformed query: {} ({})",
err.as_str(),
contextmsg
)
}
StamError::SerializationError(err) => {
format!("SerializationError: Serialization failed: {}", err)
}
StamError::DeserializationError(err) => {
format!("DeserializationError: Deserialization failed: {}", err)
}
StamError::BuildError(err, contextmsg) => {
format!("BuildError: Error during build: {} ({})", err, contextmsg)
}
StamError::StoreError(err, contextmsg) => {
format!("StoreError: Error during store: {} ({}) ", err, contextmsg)
}
StamError::WrongSelectorType(contextmsg) => format!(
"WrongSelectorType: Selector is not of the right type here ({})",
contextmsg
),
StamError::WrongSelectorTarget(contextmsg) => format!(
"WrongSelectorTarget: Selector is not applied on the right target ({})",
contextmsg
),
StamError::CursorOutOfBounds(cursor, contextmsg) => {
format!("CursorOutOfBounds: {:?} ({}) ", cursor, contextmsg)
}
StamError::InvalidOffset(begincursor, endcursor, contextmsg) => format!(
"InvalidOffset: begin cursor {:?} must be before end cursor {:?} ({}) ",
begincursor, endcursor, contextmsg
),
StamError::InvalidCursor(s, contextmsg) => {
format!("InvalidCursor: {:?} ({}) ", s, contextmsg)
}
StamError::NoTarget(contextmsg) => {
format!("NoTarget: Annotation has no target ({})", contextmsg)
}
StamError::NoText(contextmsg) => {
format!("NoText: Annotation has no text ({})", contextmsg)
}
StamError::InUse(contextmsg) => format!(
"InUse: Item can't be removed because it is being referenced ({})",
contextmsg
),
StamError::IncompleteError(data, contextmsg) => {
format!(
"IncompleteError: Not enough data to build: {} ({})",
data, contextmsg
)
}
StamError::ValueError(value, contextmsg) => {
format!("ValueError: Unexpected value: {} - ({})", value, contextmsg)
}
#[cfg(feature = "transpose")]
StamError::TransposeError(msg, contextmsg) => {
format!(
"TransposeError: Unable to transpose: {} - ({})",
msg, contextmsg
)
}
#[cfg(feature = "translate")]
StamError::TranslateError(msg, contextmsg) => {
format!(
"TranslateError: Unable to translate: {} - ({})",
msg, contextmsg
)
}
StamError::ValidationError(msg, contextmsg) => {
format!(
"ValidationError: Failed to validate: {} - ({})",
msg, contextmsg
)
}
StamError::UndefinedVariable(varname, contextmsg) => {
format!(
"UndefinedVariable: Undefined variable in search query: {} - ({})",
varname, contextmsg
)
}
StamError::VariableNotFoundError(var, tp, contextmsg) => {
if let Some(tp) = tp {
format!(
"VariableNotFoundError: variable ?{} of type {} not found ({})",
var, tp, contextmsg
)
} else {
format!(
"VariableNotFoundError: variable ?{} not found ({})",
var, contextmsg
)
}
}
StamError::OtherError(contextmsg) => {
format!("OtherError: {}", contextmsg)
}
}
}
}
impl fmt::Display for StamError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let errmsg: String = String::from(self);
write!(f, "[StamError] {}", errmsg)
}
}
impl std::error::Error for StamError {}
impl serde::ser::Error for StamError {
fn custom<T>(msg: T) -> Self
where
T: fmt::Display,
{
StamError::SerializationError(format!("{}", msg))
}
}
impl serde::de::Error for StamError {
fn custom<T>(msg: T) -> Self
where
T: fmt::Display,
{
StamError::DeserializationError(format!("{}", msg))
}
}
impl From<std::io::Error> for StamError {
fn from(value: std::io::Error) -> Self {
StamError::IOError(value, String::new(), "")
}
}