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