use super::K;
use crate::qtype;
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IOError;
pub enum Error {
InvalidDateTime,
IO(IOError),
InvalidCast {
from: &'static str,
to: &'static str,
},
InvalidCastList(&'static str),
IndexOutOfBounds { length: usize, index: usize },
InvalidOperation {
operator: &'static str,
operand_type: &'static str,
expected: Option<&'static str>,
},
LengthMismatch {
key_length: usize,
value_length: usize,
},
NoSuchColumn(String),
InsertWrongElement {
is_insert: bool,
destination: &'static str,
expected: &'static str,
},
PopFromEmptyList,
Object(K),
}
impl Error {
pub(crate) fn invalid_cast(from: i8, to: i8) -> Self {
Self::InvalidCast {
from: type_to_string(from),
to: type_to_string(to),
}
}
pub(crate) fn invalid_cast_list(from: i8) -> Self {
Self::InvalidCastList(type_to_string(from))
}
pub(crate) fn index_out_of_bounds(length: usize, index: usize) -> Self {
Self::IndexOutOfBounds { length, index }
}
pub(crate) fn invalid_operation(
operator: &'static str,
operand_type: i8,
expected: Option<i8>,
) -> Self {
Self::InvalidOperation {
operator,
operand_type: type_to_string(operand_type),
expected: expected.map(|type_id| type_to_string(type_id)),
}
}
pub(crate) fn length_mismatch(key_length: usize, value_length: usize) -> Self {
Self::LengthMismatch {
key_length,
value_length,
}
}
pub(crate) fn no_such_column(column: String) -> Self {
Self::NoSuchColumn(column)
}
pub(crate) fn insert_wrong_element(
is_insert: bool,
destination: i8,
expected: &'static str,
) -> Self {
Self::InsertWrongElement {
is_insert,
destination: type_to_string(destination),
expected,
}
}
pub(crate) fn pop_from_empty_list() -> Self {
Self::PopFromEmptyList
}
pub(crate) fn object(returned: K) -> Self {
Self::Object(returned)
}
pub fn into_inner(self) -> Option<K> {
match self {
Self::Object(object) => Some(object),
_ => None,
}
}
}
impl From<IOError> for Error {
fn from(error: IOError) -> Self {
Self::IO(error)
}
}
impl PartialEq<Self> for Error {
fn eq(&self, other: &Error) -> bool {
match (self, other) {
(Self::IO(left), Self::IO(right)) => left.to_string() == right.to_string(),
(Self::IO(_), _) => false,
(Self::InvalidCast { from: f, to: t }, Self::InvalidCast { from: f2, to: t2 }) => {
f == f2 && t == t2
}
(Self::InvalidCastList(left), Self::InvalidCastList(right)) => left == right,
(
Self::IndexOutOfBounds {
length: l,
index: i,
},
Self::IndexOutOfBounds {
length: l2,
index: i2,
},
) => l == l2 && i == i2,
(
Self::InvalidOperation {
operator: o,
operand_type: ot,
expected: e,
},
Self::InvalidOperation {
operator: o2,
operand_type: ot2,
expected: e2,
},
) => o == o2 && ot == ot2 && e == e2,
(
Self::LengthMismatch {
key_length: k,
value_length: l,
},
Self::LengthMismatch {
key_length: k2,
value_length: l2,
},
) => k == k2 && l == l2,
(Self::NoSuchColumn(left), Self::NoSuchColumn(right)) => left == right,
(
Self::InsertWrongElement {
is_insert: i,
destination: d,
expected: e,
},
Self::InsertWrongElement {
is_insert: i2,
destination: d2,
expected: e2,
},
) => i == i2 && d == d2 && e == e2,
(Self::Object(left), Self::Object(right)) => {
left.0.qtype == right.0.qtype && left.0.attribute == right.0.attribute
}
(Self::PopFromEmptyList, Self::PopFromEmptyList) => true,
_ => false,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::InvalidDateTime => write!(f, "invalid datetime"),
Self::IO(error) => write!(f, "IO error: {}", error),
Self::InvalidCast { from, to } => write!(f, "invalid cast from {} to {}", from, to),
Self::InvalidCastList(from) => {
write!(f, "invalid cast from {} to list of generics T", from)
}
Self::IndexOutOfBounds { length, index } => write!(
f,
"index out of bounds: specified {} but length is {}",
index, length
),
Self::InvalidOperation {
operator,
operand_type,
expected,
} => match expected {
Some(expected_type) => write!(
f,
"invalid operation {} on {}. expected: {}",
operator, operand_type, expected_type
),
None => write!(f, "invalid operation {} on {}", operator, operand_type),
},
Self::LengthMismatch {
key_length,
value_length,
} => write!(
f,
"key-value length mismatch: {} and {}",
key_length, value_length
),
Self::NoSuchColumn(column) => write!(f, "no such column: {}", column),
Self::InsertWrongElement {
is_insert,
destination,
expected,
} => {
let operation = match is_insert {
true => "insert",
false => "push",
};
write!(
f,
"{} wrong element to {}: expected {}",
operation, destination, expected
)
}
Self::Object(object) => write!(f, "{}", object),
Self::PopFromEmptyList => write!(f, "pop from empty list"),
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::InvalidDateTime => write!(f, "invalid datetime"),
Self::IO(error) => write!(f, "IO error: {:?}", error),
Self::InvalidCast { from, to } => write!(f, "invalid cast from {} to {}", from, to),
Self::InvalidCastList(from) => {
write!(f, "invalid cast from {} to list of generics T", from)
}
Self::IndexOutOfBounds { length, index } => write!(
f,
"index out of bounds: specified {} but length is {}",
index, length
),
Self::InvalidOperation {
operator,
operand_type,
expected,
} => match expected {
Some(expected_type) => write!(
f,
"invalid operation {} on {}. expected: {}",
operator, operand_type, expected_type
),
None => write!(f, "invalid operation {} on {}", operator, operand_type),
},
Self::LengthMismatch {
key_length,
value_length,
} => write!(
f,
"key-value length mismatch: {} and {}",
key_length, value_length
),
Self::NoSuchColumn(column) => write!(f, "no such column: {}", column),
Self::InsertWrongElement {
is_insert,
destination,
expected,
} => {
let operation = match is_insert {
true => "insert",
false => "push",
};
write!(
f,
"{} wrong element to {}: expected {}",
operation, destination, expected
)
}
Self::Object(object) => write!(f, "{}", object),
Self::PopFromEmptyList => write!(f, "pop from empty list"),
}
}
}
impl StdError for Error {}
fn type_to_string(qtype: i8) -> &'static str {
match qtype {
qtype::BOOL_ATOM => "bool",
qtype::GUID_ATOM => "guid",
qtype::BYTE_ATOM => "byte",
qtype::SHORT_ATOM => "short",
qtype::INT_ATOM => "int",
qtype::LONG_ATOM => "long",
qtype::REAL_ATOM => "real",
qtype::FLOAT_ATOM => "float",
qtype::CHAR => "char",
qtype::SYMBOL_ATOM => "symbol",
qtype::TIMESTAMP_ATOM => "timestamp",
qtype::MONTH_ATOM => "month",
qtype::DATE_ATOM => "date",
qtype::DATETIME_ATOM => "datetime",
qtype::TIMESPAN_ATOM => "timespan",
qtype::MINUTE_ATOM => "minute",
qtype::SECOND_ATOM => "second",
qtype::TIME_ATOM => "time",
qtype::COMPOUND_LIST => "compound list",
qtype::BOOL_LIST => "bool list",
qtype::GUID_LIST => "guid list",
qtype::BYTE_LIST => "byte list",
qtype::SHORT_LIST => "short list",
qtype::INT_LIST => "int list",
qtype::LONG_LIST => "long list",
qtype::REAL_LIST => "real list",
qtype::FLOAT_LIST => "float list",
qtype::STRING => "string",
qtype::SYMBOL_LIST => "symbol list",
qtype::TIMESTAMP_LIST => "timestamp list",
qtype::MONTH_LIST => "month list",
qtype::DATE_LIST => "date list",
qtype::DATETIME_LIST => "datetime list",
qtype::TIMESPAN_LIST => "timespan list",
qtype::MINUTE_LIST => "minute list",
qtype::SECOND_LIST => "second list",
qtype::TIME_LIST => "time list",
qtype::TABLE => "table",
qtype::DICTIONARY => "dictionary",
qtype::NULL => "null",
qtype::SORTED_DICTIONARY => "sorted dictionary",
qtype::ERROR => "error",
_ => "not supported",
}
}