@@ -12,7 +12,6 @@ use arbitrary::Arbitrary;
1212use bytemuck_derive:: { Pod , Zeroable } ;
1313#[ cfg( feature = "serde" ) ]
1414use serde_derive:: { Deserialize , Serialize } ;
15- pub use solana_pubkey_error:: PubkeyError ;
1615#[ cfg( any( feature = "std" , target_arch = "wasm32" ) ) ]
1716use std:: vec:: Vec ;
1817#[ cfg( feature = "borsh" ) ]
2928 } ,
3029 num_traits:: { FromPrimitive , ToPrimitive } ,
3130 solana_decode_error:: DecodeError ,
31+ solana_program_error:: ProgramError ,
3232} ;
3333#[ cfg( target_arch = "wasm32" ) ]
3434use {
@@ -55,6 +55,95 @@ const PDA_MARKER: &[u8; 21] = b"ProgramDerivedAddress";
5555#[ cfg( target_os = "solana" ) ]
5656const SUCCESS : u64 = 0 ;
5757
58+ // Use strum when testing to ensure our FromPrimitive
59+ // impl is exhaustive
60+ #[ cfg_attr( test, derive( strum_macros:: FromRepr , strum_macros:: EnumIter ) ) ]
61+ #[ cfg_attr( feature = "serde" , derive( serde_derive:: Serialize ) ) ]
62+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
63+ pub enum PubkeyError {
64+ /// Length of the seed is too long for address generation
65+ MaxSeedLengthExceeded ,
66+ InvalidSeeds ,
67+ IllegalOwner ,
68+ }
69+
70+ impl ToPrimitive for PubkeyError {
71+ #[ inline]
72+ fn to_i64 ( & self ) -> Option < i64 > {
73+ Some ( match * self {
74+ PubkeyError :: MaxSeedLengthExceeded => PubkeyError :: MaxSeedLengthExceeded as i64 ,
75+ PubkeyError :: InvalidSeeds => PubkeyError :: InvalidSeeds as i64 ,
76+ PubkeyError :: IllegalOwner => PubkeyError :: IllegalOwner as i64 ,
77+ } )
78+ }
79+ #[ inline]
80+ fn to_u64 ( & self ) -> Option < u64 > {
81+ self . to_i64 ( ) . map ( |x| x as u64 )
82+ }
83+ }
84+
85+ impl FromPrimitive for PubkeyError {
86+ #[ inline]
87+ fn from_i64 ( n : i64 ) -> Option < Self > {
88+ if n == PubkeyError :: MaxSeedLengthExceeded as i64 {
89+ Some ( PubkeyError :: MaxSeedLengthExceeded )
90+ } else if n == PubkeyError :: InvalidSeeds as i64 {
91+ Some ( PubkeyError :: InvalidSeeds )
92+ } else if n == PubkeyError :: IllegalOwner as i64 {
93+ Some ( PubkeyError :: IllegalOwner )
94+ } else {
95+ None
96+ }
97+ }
98+ #[ inline]
99+ fn from_u64 ( n : u64 ) -> Option < Self > {
100+ Self :: from_i64 ( n as i64 )
101+ }
102+ }
103+
104+ #[ cfg( feature = "std" ) ]
105+ impl std:: error:: Error for PubkeyError { }
106+
107+ impl fmt:: Display for PubkeyError {
108+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
109+ match self {
110+ PubkeyError :: MaxSeedLengthExceeded => {
111+ f. write_str ( "Length of the seed is too long for address generation" )
112+ }
113+ PubkeyError :: InvalidSeeds => {
114+ f. write_str ( "Provided seeds do not result in a valid address" )
115+ }
116+ PubkeyError :: IllegalOwner => f. write_str ( "Provided owner is not allowed" ) ,
117+ }
118+ }
119+ }
120+
121+ impl < T > DecodeError < T > for PubkeyError {
122+ fn type_of ( ) -> & ' static str {
123+ "PubkeyError"
124+ }
125+ }
126+ impl From < u64 > for PubkeyError {
127+ fn from ( error : u64 ) -> Self {
128+ match error {
129+ 0 => PubkeyError :: MaxSeedLengthExceeded ,
130+ 1 => PubkeyError :: InvalidSeeds ,
131+ 2 => PubkeyError :: IllegalOwner ,
132+ _ => panic ! ( "Unsupported PubkeyError" ) ,
133+ }
134+ }
135+ }
136+
137+ impl From < PubkeyError > for ProgramError {
138+ fn from ( error : PubkeyError ) -> Self {
139+ match error {
140+ PubkeyError :: MaxSeedLengthExceeded => Self :: MaxSeedLengthExceeded ,
141+ PubkeyError :: InvalidSeeds => Self :: InvalidSeeds ,
142+ PubkeyError :: IllegalOwner => Self :: IllegalOwner ,
143+ }
144+ }
145+ }
146+
58147/// The address of a [Solana account][acc].
59148///
60149/// Some account addresses are [ed25519] public keys, with corresponding secret
@@ -1296,6 +1385,18 @@ mod tests {
12961385 assert ! ( pubkey_from_seed_by_marker( & PDA_MARKER [ 1 ..] ) . is_ok( ) ) ;
12971386 }
12981387
1388+ #[ test]
1389+ fn test_pubkey_error_from_primitive_exhaustive ( ) {
1390+ for variant in PubkeyError :: iter ( ) {
1391+ let variant_i64 = variant. clone ( ) as i64 ;
1392+ assert_eq ! (
1393+ PubkeyError :: from_repr( variant_i64 as usize ) ,
1394+ PubkeyError :: from_i64( variant_i64)
1395+ ) ;
1396+ assert_eq ! ( PubkeyError :: from( variant_i64 as u64 ) , variant) ;
1397+ }
1398+ }
1399+
12991400 #[ test]
13001401 fn test_parse_pubkey_error_from_primitive_exhaustive ( ) {
13011402 for variant in ParsePubkeyError :: iter ( ) {
0 commit comments