Skip to main content

rialo_s_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/rialo_s_program_error/enum.ProgramError.html
22/// [`ProgramError::Custom`]: https://docs.rs/solana-program-error/latest/rialo_s_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 num_derive::FromPrimitive;
37
38    use super::*;
39
40    #[test]
41    fn test_decode_custom_error_to_enum() {
42        #[derive(Debug, FromPrimitive, PartialEq, Eq)]
43        enum TestEnum {
44            A,
45            B,
46            C,
47        }
48        impl<T> DecodeError<T> for TestEnum {
49            fn type_of() -> &'static str {
50                "TestEnum"
51            }
52        }
53        assert_eq!(TestEnum::decode_custom_error_to_enum(0), Some(TestEnum::A));
54        assert_eq!(TestEnum::decode_custom_error_to_enum(1), Some(TestEnum::B));
55        assert_eq!(TestEnum::decode_custom_error_to_enum(2), Some(TestEnum::C));
56        let option: Option<TestEnum> = TestEnum::decode_custom_error_to_enum(3);
57        assert_eq!(option, None);
58    }
59}