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