use std::{array::TryFromSliceError, io, num::TryFromIntError, str::Utf8Error, sync::Arc};
use bounded_vec::BoundedVecOutOfBounds;
use hex::FromHexError;
use thiserror::Error;
#[derive(Clone, Error, Debug)]
pub enum SerializationError {
#[error("io error: {0}")]
Io(#[from] Arc<io::Error>),
#[error("parse error: {0}")]
Parse(&'static str),
#[error("string was not UTF-8: {0}")]
Utf8Error(#[from] Utf8Error),
#[error("slice was the wrong length: {0}")]
TryFromSliceError(#[from] TryFromSliceError),
#[error("CompactSize too large: {0}")]
TryFromIntError(#[from] TryFromIntError),
#[error("string was not hex: {0}")]
FromHexError(#[from] FromHexError),
#[error("input couldn't be parsed as a zatoshi `Amount`: {source}")]
Amount {
#[from]
source: crate::amount::Error,
},
#[error("transaction balance is non-zero but doesn't have Sapling shielded spends or outputs")]
BadTransactionBalance,
}
impl From<SerializationError> for io::Error {
fn from(e: SerializationError) -> Self {
match e {
SerializationError::Io(e) => {
Arc::try_unwrap(e).unwrap_or_else(|e| io::Error::new(e.kind(), e.to_string()))
}
SerializationError::Parse(msg) => io::Error::new(io::ErrorKind::InvalidData, msg),
SerializationError::Utf8Error(e) => io::Error::new(io::ErrorKind::InvalidData, e),
SerializationError::TryFromSliceError(e) => {
io::Error::new(io::ErrorKind::InvalidData, e)
}
SerializationError::TryFromIntError(e) => io::Error::new(io::ErrorKind::InvalidData, e),
SerializationError::FromHexError(e) => io::Error::new(io::ErrorKind::InvalidData, e),
SerializationError::Amount { source } => {
io::Error::new(io::ErrorKind::InvalidData, source)
}
SerializationError::BadTransactionBalance => io::Error::new(
io::ErrorKind::InvalidData,
"bad transaction balance: non-zero with no Sapling shielded spends or outputs",
),
}
}
}
impl From<crate::Error> for SerializationError {
fn from(e: crate::Error) -> Self {
match e {
crate::Error::InvalidConsensusBranchId => Self::Parse("invalid consensus branch id"),
crate::Error::Io(e) => Self::Io(e),
crate::Error::MissingNetworkUpgrade => Self::Parse("missing network upgrade"),
crate::Error::Amount(_) => Self::BadTransactionBalance,
crate::Error::Conversion(_) => {
Self::Parse("Zebra's type could not be converted to its librustzcash equivalent")
}
}
}
}
impl From<io::Error> for SerializationError {
fn from(value: io::Error) -> Self {
Arc::new(value).into()
}
}
impl From<BoundedVecOutOfBounds> for SerializationError {
fn from(_: BoundedVecOutOfBounds) -> Self {
SerializationError::Parse("vector length out of bounds")
}
}