use core::{
fmt::{self, Debug, Formatter},
u16, u8,
};
use crate::{
bytesrepr,
contract_api::turef::AccessRightsError,
system_contracts::{mint, pos},
value::{
account::{AddKeyFailure, RemoveKeyFailure, SetThresholdFailure, UpdateKeyFailure},
CLValueError,
},
};
const RESERVED_ERROR_MAX: u32 = u16::MAX as u32;
const POS_ERROR_OFFSET: u32 = RESERVED_ERROR_MAX - u8::MAX as u32;
const MINT_ERROR_OFFSET: u32 = (POS_ERROR_OFFSET - 1) - u8::MAX as u32;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Error {
None,
MissingArgument,
InvalidArgument,
Deserialize,
Read,
ValueNotFound,
ContractNotFound,
GetKey,
UnexpectedKeyVariant,
UnexpectedValueVariant,
UnexpectedContractRefVariant,
InvalidPurseName,
InvalidPurse,
UpgradeContractAtURef,
Transfer,
NoAccessRights,
ValueConversion,
CLTypeMismatch,
EarlyEndOfStream,
FormattingError,
LeftOverBytes,
OutOfMemoryError,
MaxKeysLimit,
DuplicateKey,
PermissionDenied,
MissingKey,
ThresholdViolation,
KeyManagementThresholdError,
DeploymentThresholdError,
PermissionDeniedError,
InsufficientTotalWeight,
InvalidSystemContract,
PurseNotCreated,
Unhandled,
BufferTooSmall,
HostBufferEmpty,
HostBufferFull,
Mint(u8),
ProofOfStake(u8),
User(u16),
}
impl From<bytesrepr::Error> for Error {
fn from(error: bytesrepr::Error) -> Self {
match error {
bytesrepr::Error::EarlyEndOfStream => Error::EarlyEndOfStream,
bytesrepr::Error::FormattingError => Error::FormattingError,
bytesrepr::Error::LeftOverBytes => Error::LeftOverBytes,
bytesrepr::Error::OutOfMemoryError => Error::OutOfMemoryError,
}
}
}
impl From<AddKeyFailure> for Error {
fn from(error: AddKeyFailure) -> Self {
match error {
AddKeyFailure::MaxKeysLimit => Error::MaxKeysLimit,
AddKeyFailure::DuplicateKey => Error::DuplicateKey,
AddKeyFailure::PermissionDenied => Error::PermissionDenied,
}
}
}
impl From<UpdateKeyFailure> for Error {
fn from(error: UpdateKeyFailure) -> Self {
match error {
UpdateKeyFailure::MissingKey => Error::MissingKey,
UpdateKeyFailure::PermissionDenied => Error::PermissionDenied,
UpdateKeyFailure::ThresholdViolation => Error::ThresholdViolation,
}
}
}
impl From<RemoveKeyFailure> for Error {
fn from(error: RemoveKeyFailure) -> Self {
match error {
RemoveKeyFailure::MissingKey => Error::MissingKey,
RemoveKeyFailure::PermissionDenied => Error::PermissionDenied,
RemoveKeyFailure::ThresholdViolation => Error::ThresholdViolation,
}
}
}
impl From<SetThresholdFailure> for Error {
fn from(error: SetThresholdFailure) -> Self {
match error {
SetThresholdFailure::KeyManagementThresholdError => Error::KeyManagementThresholdError,
SetThresholdFailure::DeploymentThresholdError => Error::DeploymentThresholdError,
SetThresholdFailure::PermissionDeniedError => Error::PermissionDeniedError,
SetThresholdFailure::InsufficientTotalWeight => Error::InsufficientTotalWeight,
}
}
}
impl From<AccessRightsError> for Error {
fn from(error: AccessRightsError) -> Self {
match error {
AccessRightsError::NoAccessRights => Error::NoAccessRights,
}
}
}
impl From<CLValueError> for Error {
fn from(error: CLValueError) -> Self {
match error {
CLValueError::Serialization(bytesrepr_error) => bytesrepr_error.into(),
CLValueError::Type(_) => Error::CLTypeMismatch,
}
}
}
impl From<mint::Error> for Error {
fn from(error: mint::Error) -> Self {
Error::Mint(error as u8)
}
}
impl From<pos::Error> for Error {
fn from(error: pos::Error) -> Self {
Error::ProofOfStake(error as u8)
}
}
impl From<Error> for u32 {
fn from(error: Error) -> Self {
match error {
Error::None => 1,
Error::MissingArgument => 2,
Error::InvalidArgument => 3,
Error::Deserialize => 4,
Error::Read => 5,
Error::ValueNotFound => 6,
Error::ContractNotFound => 7,
Error::GetKey => 8,
Error::UnexpectedKeyVariant => 9,
Error::UnexpectedValueVariant => 10,
Error::UnexpectedContractRefVariant => 11,
Error::InvalidPurseName => 12,
Error::InvalidPurse => 13,
Error::UpgradeContractAtURef => 14,
Error::Transfer => 15,
Error::NoAccessRights => 16,
Error::ValueConversion => 17,
Error::CLTypeMismatch => 18,
Error::EarlyEndOfStream => 19,
Error::FormattingError => 20,
Error::LeftOverBytes => 21,
Error::OutOfMemoryError => 22,
Error::MaxKeysLimit => 23,
Error::DuplicateKey => 24,
Error::PermissionDenied => 25,
Error::MissingKey => 26,
Error::ThresholdViolation => 27,
Error::KeyManagementThresholdError => 28,
Error::DeploymentThresholdError => 29,
Error::PermissionDeniedError => 30,
Error::InsufficientTotalWeight => 31,
Error::InvalidSystemContract => 32,
Error::PurseNotCreated => 33,
Error::Unhandled => 34,
Error::BufferTooSmall => 35,
Error::HostBufferEmpty => 36,
Error::HostBufferFull => 37,
Error::Mint(value) => MINT_ERROR_OFFSET + u32::from(value),
Error::ProofOfStake(value) => POS_ERROR_OFFSET + u32::from(value),
Error::User(value) => RESERVED_ERROR_MAX + 1 + u32::from(value),
}
}
}
impl Debug for Error {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Error::None => write!(f, "Error::None")?,
Error::MissingArgument => write!(f, "Error::MissingArgument")?,
Error::InvalidArgument => write!(f, "Error::InvalidArgument")?,
Error::Deserialize => write!(f, "Error::Deserialize")?,
Error::Read => write!(f, "Error::Read")?,
Error::ValueNotFound => write!(f, "Error::ValueNotFound")?,
Error::ContractNotFound => write!(f, "Error::ContractNotFound")?,
Error::GetKey => write!(f, "Error::GetKey")?,
Error::UnexpectedKeyVariant => write!(f, "Error::UnexpectedKeyVariant")?,
Error::UnexpectedValueVariant => write!(f, "Error::UnexpectedValueVariant")?,
Error::UnexpectedContractRefVariant => {
write!(f, "Error::UnexpectedContractRefVariant")?
}
Error::InvalidPurseName => write!(f, "Error::InvalidPurseName")?,
Error::InvalidPurse => write!(f, "Error::InvalidPurse")?,
Error::UpgradeContractAtURef => write!(f, "Error::UpgradeContractAtURef")?,
Error::Transfer => write!(f, "Error::Transfer")?,
Error::NoAccessRights => write!(f, "Error::NoAccessRights")?,
Error::ValueConversion => write!(f, "Error::ValueConversion")?,
Error::CLTypeMismatch => write!(f, "Error::CLTypeMismatch")?,
Error::EarlyEndOfStream => write!(f, "Error::EarlyEndOfStream")?,
Error::FormattingError => write!(f, "Error::FormattingError")?,
Error::LeftOverBytes => write!(f, "Error::LeftOverBytes")?,
Error::OutOfMemoryError => write!(f, "Error::OutOfMemoryError")?,
Error::MaxKeysLimit => write!(f, "Error::MaxKeysLimit")?,
Error::DuplicateKey => write!(f, "Error::DuplicateKey")?,
Error::PermissionDenied => write!(f, "Error::PermissionDenied")?,
Error::MissingKey => write!(f, "Error::MissingKey")?,
Error::ThresholdViolation => write!(f, "Error::ThresholdViolation")?,
Error::KeyManagementThresholdError => write!(f, "Error::KeyManagementThresholdError")?,
Error::DeploymentThresholdError => write!(f, "Error::DeploymentThresholdError")?,
Error::PermissionDeniedError => write!(f, "Error::PermissionDeniedError")?,
Error::InsufficientTotalWeight => write!(f, "Error::InsufficientTotalWeight")?,
Error::InvalidSystemContract => write!(f, "Error::InvalidSystemContract")?,
Error::PurseNotCreated => write!(f, "Error::PurseNotCreated")?,
Error::Unhandled => write!(f, "Error::Unhandled")?,
Error::BufferTooSmall => write!(f, "Error::BufferTooSmall")?,
Error::HostBufferEmpty => write!(f, "Error::HostBufferEmpty")?,
Error::HostBufferFull => write!(f, "Error::HostBufferFull")?,
Error::Mint(value) => write!(f, "Error::Mint({})", value)?,
Error::ProofOfStake(value) => write!(f, "Error::ProofOfStake({})", value)?,
Error::User(value) => write!(f, "Error::User({})", value)?,
}
write!(f, " [{}]", u32::from(*self))
}
}
pub fn i32_from(result: Result<(), Error>) -> i32 {
match result {
Ok(()) => 0,
Err(error) => u32::from(error) as i32,
}
}
pub fn result_from(value: i32) -> Result<(), Error> {
match value {
0 => Ok(()),
1 => Err(Error::None),
2 => Err(Error::MissingArgument),
3 => Err(Error::InvalidArgument),
4 => Err(Error::Deserialize),
5 => Err(Error::Read),
6 => Err(Error::ValueNotFound),
7 => Err(Error::ContractNotFound),
8 => Err(Error::GetKey),
9 => Err(Error::UnexpectedKeyVariant),
10 => Err(Error::UnexpectedValueVariant),
11 => Err(Error::UnexpectedContractRefVariant),
12 => Err(Error::InvalidPurseName),
13 => Err(Error::InvalidPurse),
14 => Err(Error::UpgradeContractAtURef),
15 => Err(Error::Transfer),
16 => Err(Error::NoAccessRights),
17 => Err(Error::ValueConversion),
18 => Err(Error::CLTypeMismatch),
19 => Err(Error::EarlyEndOfStream),
20 => Err(Error::FormattingError),
21 => Err(Error::LeftOverBytes),
22 => Err(Error::OutOfMemoryError),
23 => Err(Error::MaxKeysLimit),
24 => Err(Error::DuplicateKey),
25 => Err(Error::PermissionDenied),
26 => Err(Error::MissingKey),
27 => Err(Error::ThresholdViolation),
28 => Err(Error::KeyManagementThresholdError),
29 => Err(Error::DeploymentThresholdError),
30 => Err(Error::PermissionDeniedError),
31 => Err(Error::InsufficientTotalWeight),
32 => Err(Error::InvalidSystemContract),
33 => Err(Error::PurseNotCreated),
34 => Err(Error::Unhandled),
35 => Err(Error::BufferTooSmall),
36 => Err(Error::HostBufferEmpty),
37 => Err(Error::HostBufferFull),
_ => {
if value > RESERVED_ERROR_MAX as i32 && value <= (2 * RESERVED_ERROR_MAX + 1) as i32 {
Err(Error::User(value as u16))
} else if value >= POS_ERROR_OFFSET as i32 && value <= RESERVED_ERROR_MAX as i32 {
Err(Error::ProofOfStake(value as u8))
} else if value >= MINT_ERROR_OFFSET as i32 && value < POS_ERROR_OFFSET as i32 {
Err(Error::Mint(value as u8))
} else {
Err(Error::Unhandled)
}
}
}
}
#[cfg(test)]
mod tests {
use alloc::format;
use core::{i32, u16, u8};
use super::*;
fn round_trip(result: Result<(), Error>) {
let code = i32_from(result);
assert_eq!(result, result_from(code));
}
#[test]
fn error() {
assert_eq!(65_024_u32, Error::Mint(0).into());
assert_eq!(65_279_u32, Error::Mint(u8::MAX).into());
assert_eq!(65_280_u32, Error::ProofOfStake(0).into());
assert_eq!(65_535_u32, Error::ProofOfStake(u8::MAX).into());
assert_eq!(65_536_u32, Error::User(0).into());
assert_eq!(131_071_u32, Error::User(u16::MAX).into());
assert_eq!("Error::GetKey [8]", &format!("{:?}", Error::GetKey));
assert_eq!("Error::Mint(0) [65024]", &format!("{:?}", Error::Mint(0)));
assert_eq!(
"Error::Mint(255) [65279]",
&format!("{:?}", Error::Mint(u8::MAX))
);
assert_eq!(
"Error::ProofOfStake(0) [65280]",
&format!("{:?}", Error::ProofOfStake(0))
);
assert_eq!(
"Error::ProofOfStake(255) [65535]",
&format!("{:?}", Error::ProofOfStake(u8::MAX))
);
assert_eq!("Error::User(0) [65536]", &format!("{:?}", Error::User(0)));
assert_eq!(
"Error::User(65535) [131071]",
&format!("{:?}", Error::User(u16::MAX))
);
assert_eq!(Err(Error::Unhandled), result_from(i32::MAX));
assert_eq!(
Err(Error::Unhandled),
result_from(MINT_ERROR_OFFSET as i32 - 1)
);
assert_eq!(Err(Error::Unhandled), result_from(-1));
assert_eq!(Err(Error::Unhandled), result_from(i32::MIN));
round_trip(Ok(()));
round_trip(Err(Error::None));
round_trip(Err(Error::MissingArgument));
round_trip(Err(Error::InvalidArgument));
round_trip(Err(Error::Deserialize));
round_trip(Err(Error::Read));
round_trip(Err(Error::ValueNotFound));
round_trip(Err(Error::ContractNotFound));
round_trip(Err(Error::GetKey));
round_trip(Err(Error::UnexpectedKeyVariant));
round_trip(Err(Error::UnexpectedValueVariant));
round_trip(Err(Error::UnexpectedContractRefVariant));
round_trip(Err(Error::InvalidPurseName));
round_trip(Err(Error::InvalidPurse));
round_trip(Err(Error::UpgradeContractAtURef));
round_trip(Err(Error::Transfer));
round_trip(Err(Error::NoAccessRights));
round_trip(Err(Error::ValueConversion));
round_trip(Err(Error::CLTypeMismatch));
round_trip(Err(Error::EarlyEndOfStream));
round_trip(Err(Error::FormattingError));
round_trip(Err(Error::LeftOverBytes));
round_trip(Err(Error::OutOfMemoryError));
round_trip(Err(Error::MaxKeysLimit));
round_trip(Err(Error::DuplicateKey));
round_trip(Err(Error::PermissionDenied));
round_trip(Err(Error::MissingKey));
round_trip(Err(Error::ThresholdViolation));
round_trip(Err(Error::KeyManagementThresholdError));
round_trip(Err(Error::DeploymentThresholdError));
round_trip(Err(Error::PermissionDeniedError));
round_trip(Err(Error::InsufficientTotalWeight));
round_trip(Err(Error::InvalidSystemContract));
round_trip(Err(Error::PurseNotCreated));
round_trip(Err(Error::Unhandled));
round_trip(Err(Error::BufferTooSmall));
round_trip(Err(Error::HostBufferEmpty));
round_trip(Err(Error::HostBufferFull));
round_trip(Err(Error::Mint(0)));
round_trip(Err(Error::Mint(u8::MAX)));
round_trip(Err(Error::ProofOfStake(0)));
round_trip(Err(Error::ProofOfStake(u8::MAX)));
round_trip(Err(Error::User(0)));
round_trip(Err(Error::User(u16::MAX)));
}
}