1use std::fmt;
14use std::str::FromStr;
15
16use borsh::{BorshDeserialize, BorshSerialize};
17
18#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, BorshSerialize, BorshDeserialize)]
20pub struct Pubkey([u8; 32]);
21
22impl fmt::Display for Base58Error {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::Empty => f.write_str("empty base58 string"),
26 Self::InvalidChar => f.write_str("invalid base58 character"),
27 Self::InvalidLength => f.write_str("base58 decoded to a length other than 32 bytes"),
28 }
29 }
30}
31
32impl std::error::Error for Base58Error {}
33
34#[derive(Debug, PartialEq, Eq)]
36pub enum Base58Error {
37 Empty,
39 InvalidChar,
42 InvalidLength,
44}
45
46impl Pubkey {
47 pub const fn from_bytes(b: [u8; 32]) -> Self {
49 Self(b)
50 }
51
52 pub const fn to_bytes(&self) -> [u8; 32] {
54 self.0
55 }
56
57 pub fn as_bytes(&self) -> &[u8; 32] {
59 &self.0
60 }
61
62 pub const SYSTEM: Self = Self([0x00; 32]);
64
65 pub const MEMO: Self = Self([
68 0x05, 0x4a, 0x53, 0x5a, 0x99, 0x29, 0x21, 0x06, 0x4d, 0x24, 0xe8, 0x71,
69 0x60, 0xda, 0x38, 0x7c, 0x7c, 0x35, 0xb5, 0xdd, 0xbc, 0x92, 0xbb, 0x81,
70 0xe4, 0x1f, 0xa8, 0x40, 0x41, 0x05, 0x44, 0x8d,
71 ]);
72
73 pub const SAS: Self = Self([
77 0x0f, 0x5e, 0x9e, 0xd5, 0x37, 0x1e, 0x2c, 0x70, 0x89, 0x8c, 0xa9, 0xfd,
78 0x0e, 0x77, 0xc0, 0x06, 0x5c, 0xab, 0x5d, 0xa0, 0x2e, 0x56, 0x67, 0x8b,
79 0x27, 0x13, 0x38, 0x2a, 0xf3, 0x74, 0x59, 0xb7,
80 ]);
81}
82
83impl fmt::Display for Pubkey {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.write_str(&bs58::encode(self.0).into_string())
87 }
88}
89
90impl fmt::Debug for Pubkey {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 f.debug_tuple("Pubkey").field(&bs58::encode(self.0).into_string()).finish()
94 }
95}
96
97impl FromStr for Pubkey {
98 type Err = Base58Error;
99 fn from_str(s: &str) -> Result<Self, Self::Err> {
100 if s.is_empty() {
101 return Err(Base58Error::Empty);
102 }
103 let bytes = bs58::decode(s).into_vec().map_err(|_| Base58Error::InvalidChar)?;
106 if bytes.len() != 32 {
107 return Err(Base58Error::InvalidLength);
108 }
109 let mut arr = [0u8; 32];
110 arr.copy_from_slice(&bytes);
111 Ok(Self(arr))
112 }
113}
114
115impl From<[u8; 32]> for Pubkey {
116 fn from(b: [u8; 32]) -> Self {
117 Self(b)
118 }
119}
120
121impl From<Pubkey> for [u8; 32] {
122 fn from(pk: Pubkey) -> Self {
123 pk.0
124 }
125}
126
127impl AsRef<[u8; 32]> for Pubkey {
128 fn as_ref(&self) -> &[u8; 32] {
129 &self.0
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn system_constant_is_all_zero() {
139 assert_eq!(Pubkey::SYSTEM.to_bytes(), [0x00; 32]);
140 assert_eq!(Pubkey::SYSTEM.to_string(), "11111111111111111111111111111111");
141 }
142}