solana_decode_error/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
//! Converting custom error codes to enums.
use num_traits::FromPrimitive;
/// Allows custom errors to be decoded back to their original enum.
///
/// Some Solana error enums, like [`ProgramError`], include a `Custom` variant,
/// like [`ProgramError::Custom`], that contains a `u32` error code. This code
/// may represent any error that is not covered by the error enum's named
/// variants. It is common for programs to convert their own error enums to an
/// error code and store it in the `Custom` variant, possibly with the help of
/// the [`ToPrimitive`] trait.
///
/// This trait builds on the [`FromPrimitive`] trait to help convert those error
/// codes to the original error enum they represent.
///
/// As this allows freely converting `u32` to any type that implements
/// `FromPrimitive`, it is only used correctly when the caller is certain of the
/// original error type.
///
/// [`ProgramError`]: https://docs.rs/solana-program-error/latest/solana_program_error/enum.ProgramError.html
/// [`ProgramError::Custom`]: https://docs.rs/solana-program-error/latest/solana_program_error/enum.ProgramError.html#variant.Custom
/// [`ToPrimitive`]: num_traits::ToPrimitive
pub trait DecodeError<E> {
fn decode_custom_error_to_enum(custom: u32) -> Option<E>
where
E: FromPrimitive,
{
E::from_u32(custom)
}
fn type_of() -> &'static str;
}
#[cfg(test)]
mod tests {
use {super::*, num_derive::FromPrimitive};
#[test]
fn test_decode_custom_error_to_enum() {
#[derive(Debug, FromPrimitive, PartialEq, Eq)]
enum TestEnum {
A,
B,
C,
}
impl<T> DecodeError<T> for TestEnum {
fn type_of() -> &'static str {
"TestEnum"
}
}
assert_eq!(TestEnum::decode_custom_error_to_enum(0), Some(TestEnum::A));
assert_eq!(TestEnum::decode_custom_error_to_enum(1), Some(TestEnum::B));
assert_eq!(TestEnum::decode_custom_error_to_enum(2), Some(TestEnum::C));
let option: Option<TestEnum> = TestEnum::decode_custom_error_to_enum(3);
assert_eq!(option, None);
}
}