use bincode::{Error as BincodeError, ErrorKind as BincodeErrorKind};
use peg::{error::ParseError, str::LineCol};
use sanakirja::Error as SanakirjaError;
use std::convert::Infallible;
use std::sync::TryLockError;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
IO(#[from] std::io::Error),
#[error("Storage corruption")]
Corruption,
#[error("Lock poisoning")]
Poison,
#[error("Internal")]
Internal,
#[error("Read only write attempt")]
ReadOnlyWrite,
#[error("Invalid syntax at line {line}, column {column}: {expected}")]
Syntax {
line: usize,
column: usize,
offset: usize,
expected: String,
},
#[error("Identifier {0} does not refer to a node")]
IdentifierIsNotNode(String),
#[error("Identifier {0} does not refer to an edge")]
IdentifierIsNotEdge(String),
#[error("Identifier {0} already exists")]
IdentifierExists(String),
#[error("Identifier {0} does not exists")]
UnknownIdentifier(String),
#[error("Type mismatch")]
TypeMismatch,
#[error("Index out of bounds")]
IndexOutOfBounds,
#[error("Missing node")]
MissingNode,
#[error("Missing edge")]
MissingEdge,
#[error("Attempt to delete connected node")]
DeleteConnected,
}
impl From<SanakirjaError> for Error {
fn from(error: SanakirjaError) -> Self {
match error {
SanakirjaError::IO(err) => Self::IO(err),
SanakirjaError::Poison => Self::Poison,
SanakirjaError::VersionMismatch | SanakirjaError::CRC(_) => Self::Corruption,
SanakirjaError::Corrupt(_) => Self::Corruption,
}
}
}
impl From<BincodeError> for Error {
fn from(error: BincodeError) -> Self {
match *error {
BincodeErrorKind::Io(err) => Self::IO(err),
_ => Self::Corruption,
}
}
}
impl From<Infallible> for Error {
fn from(_: Infallible) -> Self {
unreachable!()
}
}
impl From<ParseError<LineCol>> for Error {
fn from(error: ParseError<LineCol>) -> Self {
Self::Syntax {
line: error.location.line,
column: error.location.column,
offset: error.location.offset,
expected: format!("{}", error.expected),
}
}
}
impl<T> From<TryLockError<T>> for Error {
fn from(error: TryLockError<T>) -> Self {
match error {
TryLockError::Poisoned(_) => Self::Poison,
TryLockError::WouldBlock => Self::Internal,
}
}
}