solders_hash/
lib.rs

1use std::str::FromStr;
2
3use derive_more::{From, Into};
4use pyo3::prelude::*;
5use serde::{Deserialize, Serialize};
6use solana_program::hash::{
7    hash, Hash as HashOriginal, ParseHashError as ParseHashErrorOriginal, HASH_BYTES,
8};
9use solders_macros::{common_methods, pyhash, richcmp_full};
10
11use solders_traits::handle_py_err;
12use solders_traits_core::{
13    impl_display, pybytes_general_via_slice, CommonMethodsCore, PyFromBytesGeneral, PyHash,
14    RichcmpFull,
15};
16
17#[pyclass(module = "solders.hash", subclass)]
18/// A SHA-256 hash, most commonly used for blockhashes.
19///
20/// Args:
21///     hash_bytes (bytes): the hashed bytes.
22///
23#[derive(
24    Clone,
25    Copy,
26    Default,
27    Eq,
28    PartialEq,
29    Ord,
30    PartialOrd,
31    Hash,
32    Debug,
33    Deserialize,
34    Serialize,
35    From,
36    Into,
37)]
38pub struct Hash(HashOriginal);
39
40#[pyhash]
41#[richcmp_full]
42#[common_methods]
43#[pymethods]
44impl Hash {
45    #[classattr]
46    pub const LENGTH: usize = HASH_BYTES;
47
48    #[new]
49    pub fn new(hash_bytes: [u8; HASH_BYTES]) -> Self {
50        HashOriginal::new_from_array(hash_bytes).into()
51    }
52
53    #[staticmethod]
54    #[pyo3(name = "from_string")]
55    /// Create a ``Hash`` from a base-58 string.
56    ///
57    /// Args:
58    ///     s (str): The base-58 encoded string
59    ///
60    /// Returns:
61    ///     Hash: a ``Hash`` object.
62    ///
63    /// Example:
64    ///
65    ///     >>> from solders.hash import Hash
66    ///     >>> Hash.from_string("4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM")
67    ///     Hash(
68    ///         4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM,
69    ///     )
70    ///
71    pub fn new_from_string(s: &str) -> PyResult<Self> {
72        handle_py_err(HashOriginal::from_str(s))
73    }
74
75    #[staticmethod]
76    /// Create a unique Hash for tests and benchmarks.
77    ///
78    /// Returns:
79    ///     Hash: a ``Hash`` object.
80    pub fn new_unique() -> Self {
81        HashOriginal::new_unique().into()
82    }
83
84    #[staticmethod]
85    #[pyo3(name = "default")]
86    /// The default ``Hash`` object.
87    ///
88    /// Returns:
89    ///     Hash: a ``Hash`` object.
90    /// Example:
91    ///     >>> from solders.hash import Hash
92    ///     >>> Hash.default()
93    ///     Hash(
94    ///         11111111111111111111111111111111,
95    ///     )
96    pub fn new_default() -> Self {
97        Self::default()
98    }
99
100    #[staticmethod]
101    #[allow(clippy::self_named_constructors)]
102    /// Return a Sha256 hash for the given data.
103    ///
104    /// Args:
105    ///     val (bytes): the data to hash.
106    ///
107    /// Returns:
108    ///     Hash: a ``Hash`` object.
109    ///
110    /// Example:
111    ///     >>> from solders.hash import Hash
112    ///     >>> Hash.hash(b"foo")
113    ///     Hash(
114    ///         3yMApqCuCjXDWPrbjfR5mjCPTHqFG8Pux1TxQrEM35jj,
115    ///     )
116    pub fn hash(val: &[u8]) -> Self {
117        hash(val).into()
118    }
119
120    #[staticmethod]
121    /// Construct from ``bytes``. Equivalent to ``Hash.__init__`` but included for the sake of consistency.
122    ///
123    /// Args:
124    ///     raw_bytes (bytes): the hashed bytes.
125    ///
126    /// Returns:
127    ///     Hash: a ``Hash`` object.
128    ///
129    pub fn from_bytes(raw_bytes: [u8; HASH_BYTES]) -> PyResult<Self> {
130        Self::py_from_bytes(&raw_bytes)
131    }
132}
133
134impl PyFromBytesGeneral for Hash {
135    fn py_from_bytes_general(raw: &[u8]) -> PyResult<Self> {
136        Ok(HashOriginal::new(raw).into())
137    }
138}
139
140pybytes_general_via_slice!(Hash);
141solders_traits_core::common_methods_default!(Hash);
142
143impl RichcmpFull for Hash {}
144
145impl PyHash for Hash {}
146
147impl AsRef<HashOriginal> for Hash {
148    fn as_ref(&self) -> &HashOriginal {
149        &self.0
150    }
151}
152
153impl AsRef<[u8]> for Hash {
154    fn as_ref(&self) -> &[u8] {
155        self.0.as_ref()
156    }
157}
158
159impl FromStr for Hash {
160    type Err = ParseHashErrorOriginal;
161    fn from_str(s: &str) -> Result<Self, Self::Err> {
162        HashOriginal::from_str(s).map(Hash::from)
163    }
164}
165
166impl_display!(Hash);