use alloc::vec::Vec;
use core::{
convert::{TryFrom, TryInto},
result,
};
#[cfg(feature = "std")]
use thiserror::Error;
use crate::{
bytesrepr::{self, FromBytes, ToBytes, U8_SERIALIZED_LENGTH},
CLType, CLTyped,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Error))]
#[repr(u8)]
pub enum Error {
#[cfg_attr(feature = "std", error("Missing key"))]
MissingKey = 0,
#[cfg_attr(feature = "std", error("Invalid key variant"))]
InvalidKeyVariant = 1,
#[cfg_attr(feature = "std", error("Missing value"))]
MissingValue = 2,
#[cfg_attr(feature = "std", error("Serialization error"))]
Serialization = 3,
#[cfg_attr(feature = "std", error("Transfer to bid purse error"))]
TransferToBidPurse = 4,
#[cfg_attr(feature = "std", error("Invalid amount"))]
InvalidAmount = 5,
#[cfg_attr(feature = "std", error("Bid not found"))]
BidNotFound = 6,
#[cfg_attr(feature = "std", error("Validator not found"))]
ValidatorNotFound = 7,
#[cfg_attr(feature = "std", error("Delegator not found"))]
DelegatorNotFound = 8,
#[cfg_attr(feature = "std", error("Storage error"))]
Storage = 9,
#[cfg_attr(feature = "std", error("Bonding error"))]
Bonding = 10,
#[cfg_attr(feature = "std", error("Unbonding error"))]
Unbonding = 11,
#[cfg_attr(feature = "std", error("Unable to release founder stake"))]
ReleaseFounderStake = 12,
#[cfg_attr(feature = "std", error("Unable to get purse balance"))]
GetBalance = 13,
#[cfg_attr(feature = "std", error("Invalid context"))]
InvalidContext = 14,
#[cfg_attr(feature = "std", error("Validator's funds are locked"))]
ValidatorFundsLocked = 15,
#[cfg_attr(feature = "std", error("Function must be called by system account"))]
InvalidCaller = 16,
#[cfg_attr(
feature = "std",
error("Supplied public key does not match caller's public key")
)]
InvalidPublicKey = 17,
#[cfg_attr(feature = "std", error("Validator's bond not found"))]
BondNotFound = 18,
#[cfg_attr(feature = "std", error("Unable to create purse"))]
CreatePurseFailed = 19,
#[cfg_attr(feature = "std", error("Unbond is too large"))]
UnbondTooLarge = 20,
#[cfg_attr(feature = "std", error("Bond is too small"))]
BondTooSmall = 21,
#[cfg_attr(feature = "std", error("Validators has not received any delegations"))]
MissingDelegations = 22,
#[cfg_attr(
feature = "std",
error("Mismatched era validator sets to distribute rewards")
)]
MismatchedEraValidators = 23,
#[cfg_attr(feature = "std", error("Failed to mint rewards"))]
MintReward = 24,
#[cfg_attr(feature = "std", error("Invalid number of validator slots"))]
InvalidValidatorSlotsValue = 25,
#[cfg_attr(feature = "std", error("Failed to reduce total supply"))]
MintReduceTotalSupply = 26,
#[cfg_attr(feature = "std", error("Transfer to delegators purse error"))]
TransferToDelegatorPurse = 27,
#[cfg_attr(feature = "std", error("Reward transfer to validator error"))]
ValidatorRewardTransfer = 28,
#[cfg_attr(feature = "std", error("Rewards transfer to delegator error"))]
DelegatorRewardTransfer = 29,
#[cfg_attr(feature = "std", error("Withdraw delegator reward error"))]
WithdrawDelegatorReward = 30,
#[cfg_attr(feature = "std", error("Withdraw validator reward error"))]
WithdrawValidatorReward = 31,
#[cfg_attr(feature = "std", error("Transfer to unbonding purse error"))]
TransferToUnbondingPurse = 32,
#[cfg_attr(feature = "std", error("Record era info error"))]
RecordEraInfo = 33,
#[cfg_attr(feature = "std", error("CLValue error"))]
CLValue = 34,
#[cfg_attr(feature = "std", error("Missing seigniorage recipients for given era"))]
MissingSeigniorageRecipients = 35,
#[cfg_attr(feature = "std", error("Transfer error"))]
Transfer = 36,
#[cfg_attr(feature = "std", error("Delegation rate too large"))]
DelegationRateTooLarge = 37,
#[cfg_attr(feature = "std", error("Delegator's funds are locked"))]
DelegatorFundsLocked = 38,
#[doc(hidden)]
#[cfg_attr(feature = "std", error("GasLimit"))]
GasLimit,
#[cfg(test)]
#[doc(hidden)]
#[cfg_attr(feature = "std", error("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::DelegationRateTooLarge as u8 => Ok(Error::DelegationRateTooLarge),
d if d == Error::DelegatorFundsLocked as u8 => Ok(Error::DelegatorFundsLocked),
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
}
}
#[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)
}
}
}
}
}