solana_binary_encoder/
hash.rs1use std::mem;
2use std::str::FromStr;
3use {
4 crate::{
5 sanitize::Sanitize,
6 },
7 serde_derive::{Serialize,Deserialize},
8 borsh::{
9 BorshDeserialize, BorshSerialize,
10 },
11 borsh_derive::BorshSchema,
12 std::{
13 fmt,
14 },
15 thiserror::Error,
16};
17
18pub const HASH_BYTES: usize = 32;
20const MAX_BASE58_LEN: usize = 44;
22
23#[derive(
25 Serialize,
26 Deserialize,
27 BorshSerialize,
28 BorshDeserialize,
29 BorshSchema,
30 Clone,
31 Copy,
32 Default,
33 Eq,
34 PartialEq,
35 Ord,
36 PartialOrd,
37 Hash,
38)]
39#[repr(transparent)]
40pub struct Hash(pub(crate) [u8; HASH_BYTES]);
41
42impl Hash {
43 pub fn new(hash_slice: &[u8]) -> Self {
44 Hash(<[u8; HASH_BYTES]>::try_from(hash_slice).unwrap())
45 }
46
47 pub fn to_bytes(self) -> [u8; HASH_BYTES] {
48 self.0
49 }
50}
51
52impl Sanitize for Hash {}
53
54impl From<[u8; HASH_BYTES]> for Hash {
55 fn from(from: [u8; 32]) -> Self {
56 Self(from)
57 }
58}
59
60impl AsRef<[u8]> for Hash {
61 fn as_ref(&self) -> &[u8] {
62 &self.0[..]
63 }
64}
65
66impl fmt::Debug for Hash {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f, "{}", bs58::encode(self.0).into_string())
69 }
70}
71
72impl fmt::Display for Hash {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "{}", bs58::encode(self.0).into_string())
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Error)]
79pub enum ParseHashError {
80 #[error("string decoded to wrong size for hash")]
81 WrongSize,
82 #[error("failed to decoded string to hash")]
83 Invalid,
84}
85
86impl FromStr for Hash {
87 type Err = ParseHashError;
88
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
90 if s.len() > MAX_BASE58_LEN {
91 return Err(ParseHashError::WrongSize);
92 }
93 let bytes = bs58::decode(s)
94 .into_vec()
95 .map_err(|_| ParseHashError::Invalid)?;
96 if bytes.len() != mem::size_of::<Hash>() {
97 Err(ParseHashError::WrongSize)
98 } else {
99 Ok(Hash::new(&bytes))
100 }
101 }
102}