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
24#[deprecated(since = "2.3.0", note = "Use `num_traits::FromPrimitive` instead")]
25pub trait DecodeError<E> {
26    fn decode_custom_error_to_enum(custom: u32) -> Option<E>
27    where
28        E: FromPrimitive,
29    {
30        E::from_u32(custom)
31    }
32    fn type_of() -> &'static str;
33}
34
35#[cfg(test)]
36#[allow(deprecated)]
37mod tests {
38    use {super::*, num_derive::FromPrimitive};
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}