solana_binary_encoder/
hash.rs

1use 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
18/// Size of a hash in bytes.
19pub const HASH_BYTES: usize = 32;
20/// Maximum string length of a base58 encoded hash.
21const MAX_BASE58_LEN: usize = 44;
22
23/// A hash; the 32-byte output of a hashing algorithm.
24#[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}