use alloc::vec::Vec;
use core::{
convert::{TryFrom, TryInto},
result,
};
use failure::Fail;
use crate::{
bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH},
CLType, CLTyped,
};
#[derive(Fail, Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Error {
#[fail(display = "Missing key")]
MissingKey = 0,
#[fail(display = "Invalid key variant")]
InvalidKeyVariant = 1,
#[fail(display = "Missing value")]
MissingValue = 2,
#[fail(display = "Serialization error")]
Serialization = 3,
#[fail(display = "Transfer to bid purse error")]
TransferToBidPurse = 4,
#[fail(display = "Invalid amount")]
InvalidAmount = 5,
#[fail(display = "Bid not found")]
BidNotFound = 6,
#[fail(display = "Validator not found")]
ValidatorNotFound = 7,
#[fail(display = "Delegator not found")]
DelegatorNotFound = 8,
#[fail(display = "Storage error")]
Storage = 9,
#[fail(display = "Bonding error")]
Bonding = 10,
#[fail(display = "Unbonding error")]
Unbonding = 11,
#[fail(display = "Unable to release founder stake")]
ReleaseFounderStake = 12,
#[fail(display = "Unable to get purse balance")]
GetBalance = 13,
#[fail(display = "Invalid context")]
InvalidContext = 14,
#[fail(display = "Validator's funds are locked")]
ValidatorFundsLocked = 15,
#[fail(display = "Function must be called by system account")]
InvalidCaller = 16,
#[fail(display = "Supplied public key does not match caller's public key")]
InvalidPublicKey = 17,
#[fail(display = "Validator's bond not found")]
BondNotFound = 18,
#[fail(display = "Unable to create purse")]
CreatePurseFailed = 19,
#[fail(display = "Unbond is too large")]
UnbondTooLarge = 20,
#[fail(display = "Bond is too small")]
BondTooSmall = 21,
#[fail(display = "Validators has not received any delegations")]
MissingDelegations = 22,
#[fail(display = "Mismatched era validator sets to distribute rewards")]
MismatchedEraValidators = 23,
#[fail(display = "Failed to mint rewards")]
MintReward = 24,
#[fail(display = "Invalid number of validator slots")]
InvalidValidatorSlotsValue = 25,
#[fail(display = "Failed to reduce total supply")]
MintReduceTotalSupply = 26,
#[fail(display = "Transfer to delegators purse error")]
TransferToDelegatorPurse = 27,
#[fail(display = "Reward transfer to validator error")]
ValidatorRewardTransfer = 28,
#[fail(display = "Rewards transfer to delegator error")]
DelegatorRewardTransfer = 29,
#[fail(display = "Withdraw delegator reward error")]
WithdrawDelegatorReward = 30,
#[fail(display = "Withdraw validator reward error")]
WithdrawValidatorReward = 31,
#[fail(display = "Transfer to unbonding purse error")]
TransferToUnbondingPurse = 32,
#[fail(display = "Record era info error")]
RecordEraInfo = 33,
#[fail(display = "CLValue error")]
CLValue = 34,
#[fail(display = "Missing seigniorage recipients for given era")]
MissingSeigniorageRecipients = 35,
#[fail(display = "Transfer error")]
Transfer = 36,
#[doc(hidden)]
#[fail(display = "GasLimit")]
GasLimit = 37,
#[cfg(test)]
#[doc(hidden)]
#[fail(display = "Sentinel error")]
Sentinel,
}
#[cfg(test)]
const MAX_ERROR_VALUE: u8 = Error::Sentinel as u8;
impl CLTyped for Error {
fn cl_type() -> CLType {
CLType::U8
}
}
#[doc(hidden)]
pub struct TryFromU8ForError(());
#[doc(hidden)]
impl TryFrom<u8> for Error {
type Error = TryFromU8ForError;
fn try_from(value: u8) -> result::Result<Self, Self::Error> {
match value {
d if d == Error::MissingKey as u8 => Ok(Error::MissingKey),
d if d == Error::InvalidKeyVariant as u8 => Ok(Error::InvalidKeyVariant),
d if d == Error::MissingValue as u8 => Ok(Error::MissingValue),
d if d == Error::Serialization as u8 => Ok(Error::Serialization),
d if d == Error::TransferToBidPurse as u8 => Ok(Error::TransferToBidPurse),
d if d == Error::InvalidAmount as u8 => Ok(Error::InvalidAmount),
d if d == Error::BidNotFound as u8 => Ok(Error::BidNotFound),
d if d == Error::ValidatorNotFound as u8 => Ok(Error::ValidatorNotFound),
d if d == Error::DelegatorNotFound as u8 => Ok(Error::DelegatorNotFound),
d if d == Error::Storage as u8 => Ok(Error::Storage),
d if d == Error::Bonding as u8 => Ok(Error::Bonding),
d if d == Error::Unbonding as u8 => Ok(Error::Unbonding),
d if d == Error::ReleaseFounderStake as u8 => Ok(Error::ReleaseFounderStake),
d if d == Error::GetBalance as u8 => Ok(Error::GetBalance),
d if d == Error::InvalidContext as u8 => Ok(Error::InvalidContext),
d if d == Error::ValidatorFundsLocked as u8 => Ok(Error::ValidatorFundsLocked),
d if d == Error::InvalidCaller as u8 => Ok(Error::InvalidCaller),
d if d == Error::InvalidPublicKey as u8 => Ok(Error::InvalidPublicKey),
d if d == Error::BondNotFound as u8 => Ok(Error::BondNotFound),
d if d == Error::CreatePurseFailed as u8 => Ok(Error::CreatePurseFailed),
d if d == Error::UnbondTooLarge as u8 => Ok(Error::UnbondTooLarge),
d if d == Error::BondTooSmall as u8 => Ok(Error::BondTooSmall),
d if d == Error::MissingDelegations as u8 => Ok(Error::MissingDelegations),
d if d == Error::MismatchedEraValidators as u8 => Ok(Error::MismatchedEraValidators),
d if d == Error::MintReward as u8 => Ok(Error::MintReward),
d if d == Error::MintReduceTotalSupply as u8 => Ok(Error::MintReduceTotalSupply),
d if d == Error::InvalidValidatorSlotsValue as u8 => {
Ok(Error::InvalidValidatorSlotsValue)
}
d if d == Error::TransferToDelegatorPurse as u8 => Ok(Error::TransferToDelegatorPurse),
d if d == Error::TransferToDelegatorPurse as u8 => Ok(Error::TransferToDelegatorPurse),
d if d == Error::ValidatorRewardTransfer as u8 => Ok(Error::ValidatorRewardTransfer),
d if d == Error::DelegatorRewardTransfer as u8 => Ok(Error::DelegatorRewardTransfer),
d if d == Error::WithdrawDelegatorReward as u8 => Ok(Error::WithdrawDelegatorReward),
d if d == Error::WithdrawValidatorReward as u8 => Ok(Error::WithdrawValidatorReward),
d if d == Error::TransferToUnbondingPurse as u8 => Ok(Error::TransferToUnbondingPurse),
d if d == Error::RecordEraInfo as u8 => Ok(Error::RecordEraInfo),
d if d == Error::CLValue as u8 => Ok(Error::CLValue),
d if d == Error::MissingSeigniorageRecipients as u8 => {
Ok(Error::MissingSeigniorageRecipients)
}
d if d == Error::Transfer as u8 => Ok(Error::Transfer),
d if d == Error::GasLimit as u8 => Ok(Error::GasLimit),
_ => Err(TryFromU8ForError(())),
}
}
}
impl ToBytes for Error {
fn to_bytes(&self) -> result::Result<Vec<u8>, bytesrepr::Error> {
let value = *self as u8;
value.to_bytes()
}
fn serialized_length(&self) -> usize {
U8_SERIALIZED_LENGTH
}
}
impl FromBytes for Error {
fn from_bytes(bytes: &[u8]) -> result::Result<(Self, &[u8]), bytesrepr::Error> {
let (value, rem): (u8, _) = FromBytes::from_bytes(bytes)?;
let error: Error = value
.try_into()
.map_err(|_| bytesrepr::Error::Formatting)?;
Ok((error, rem))
}
}
impl From<bytesrepr::Error> for Error {
fn from(_: bytesrepr::Error) -> Self {
Error::Serialization
}
}
pub type Result<T> = result::Result<T, Error>;
#[doc(hidden)]
pub enum PurseLookupError {
KeyNotFound,
KeyUnexpectedType,
}
impl From<PurseLookupError> for Error {
fn from(error: PurseLookupError) -> Self {
match error {
PurseLookupError::KeyNotFound => Error::MissingKey,
PurseLookupError::KeyUnexpectedType => Error::InvalidKeyVariant,
}
}
}
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
use super::{Error, TryFromU8ForError, MAX_ERROR_VALUE};
#[test]
fn error_round_trips() {
for i in 0..=u8::max_value() {
match Error::try_from(i) {
Ok(error) if i < MAX_ERROR_VALUE => assert_eq!(error as u8, i),
Ok(error) => panic!(
"value of variant {} ({}) exceeds MAX_ERROR_VALUE ({})",
error, i, MAX_ERROR_VALUE
),
Err(TryFromU8ForError(())) if i >= MAX_ERROR_VALUE => (),
Err(TryFromU8ForError(())) => {
panic!("missing conversion from u8 to error value: {}", i)
}
}
}
}
}