use std::borrow::Cow;
use std::sync::{Arc, mpsc};
use thiserror::Error;
use piecrust_uplink::{ContractError, ContractId};
use rkyv::ser::serializers::{
BufferSerializerError, CompositeSerializerError, FixedSizeScratchError,
};
pub type Compo = CompositeSerializerError<
BufferSerializerError,
FixedSizeScratchError,
std::convert::Infallible,
>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Argument buffer overflow: {len} > {max_len}")]
ArgumentBufferOverflow { len: usize, max_len: usize },
#[error("Commit error: {0}")]
CommitError(Cow<'static, str>),
#[error(transparent)]
CompositeSerializerError(Arc<Compo>),
#[error(transparent)]
ContractCacheError(Arc<std::io::Error>),
#[error("Contract does not exist: {0}")]
ContractDoesNotExist(ContractId),
#[error(transparent)]
FeedPulled(mpsc::SendError<Vec<u8>>),
#[error(transparent)]
Infallible(std::convert::Infallible),
#[error("InitalizationError: {0}")]
InitalizationError(Cow<'static, str>),
#[error("Invalid global")]
InvalidArgumentBuffer,
#[error("Invalid function: {0}")]
InvalidFunction(String),
#[error("Invalid memory")]
InvalidMemory,
#[error(
"Memory access out of bounds: offset {offset}, length {len}, memory length {mem_len}"
)]
MemoryAccessOutOfBounds {
offset: usize,
len: usize,
mem_len: usize,
},
#[error("Snapshot failure: {reason:?} {io}")]
MemorySnapshotFailure {
reason: Option<Arc<Self>>,
io: Arc<std::io::Error>,
},
#[error("Missing feed")]
MissingFeed,
#[error("Missing host data: {0}")]
MissingHostData(String),
#[error("Missing host query: {0}")]
MissingHostQuery(String),
#[error("OutOfGas")]
OutOfGas,
#[error("Panic: {0}")]
Panic(String),
#[error(transparent)]
PersistenceError(Arc<std::io::Error>),
#[error(transparent)]
RestoreError(Arc<std::io::Error>),
#[error(transparent)]
RuntimeError(dusk_wasmtime::Error),
#[error("Session error: {0}")]
SessionError(Cow<'static, str>),
#[error("Too many memories: {0}")]
TooManyMemories(usize),
#[error(transparent)]
Utf8(std::str::Utf8Error),
#[error("ValidationError")]
ValidationError,
}
impl Error {
pub fn normalize(self) -> Self {
match self {
Self::RuntimeError(rerr) => match rerr.downcast() {
Ok(err) => err,
Err(rerr) => Self::RuntimeError(rerr),
},
err => err,
}
}
}
impl From<std::convert::Infallible> for Error {
fn from(err: std::convert::Infallible) -> Self {
Self::Infallible(err)
}
}
impl From<std::str::Utf8Error> for Error {
fn from(err: std::str::Utf8Error) -> Self {
Self::Utf8(err)
}
}
impl From<dusk_wasmtime::Error> for Error {
fn from(e: dusk_wasmtime::Error) -> Self {
Error::RuntimeError(e)
}
}
impl From<Compo> for Error {
fn from(e: Compo) -> Self {
Error::CompositeSerializerError(Arc::from(e))
}
}
impl<A, B> From<rkyv::validation::CheckArchiveError<A, B>> for Error {
fn from(_e: rkyv::validation::CheckArchiveError<A, B>) -> Self {
Error::ValidationError
}
}
impl From<Error> for ContractError {
fn from(err: Error) -> Self {
match err {
Error::OutOfGas => Self::OutOfGas,
Error::Panic(msg) => Self::Panic(msg),
Error::ContractDoesNotExist(_) => Self::DoesNotExist,
_ => Self::Unknown,
}
}
}