celestia_tendermint/
hash.rs1use core::{
4 convert::TryFrom,
5 fmt::{self, Debug, Display},
6 str::FromStr,
7};
8
9use bytes::Bytes;
10use celestia_tendermint_proto::Protobuf;
11use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
12use subtle_encoding::{Encoding, Hex};
13
14use crate::serializers::cow_str::CowStr;
15use crate::{error::Error, prelude::*};
16
17pub const SHA256_HASH_SIZE: usize = 32;
19
20#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
22pub enum Algorithm {
23 Sha256,
25}
26
27#[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Default)]
29pub enum Hash {
30 Sha256([u8; SHA256_HASH_SIZE]),
32 #[default]
34 None,
35}
36
37impl Protobuf<Vec<u8>> for Hash {}
38
39impl TryFrom<Vec<u8>> for Hash {
41 type Error = Error;
42
43 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
44 if value.is_empty() {
45 return Ok(Hash::None);
46 }
47 Hash::from_bytes(Algorithm::Sha256, &value)
48 }
49}
50
51impl From<Hash> for Vec<u8> {
52 fn from(value: Hash) -> Self {
53 match value {
54 Hash::Sha256(s) => s.to_vec(),
55 Hash::None => vec![],
56 }
57 }
58}
59
60impl AsRef<[u8]> for Hash {
61 fn as_ref(&self) -> &[u8] {
62 match self {
63 Hash::Sha256(ref h) => h.as_ref(),
64 Hash::None => &[],
65 }
66 }
67}
68
69impl From<Hash> for Bytes {
70 fn from(h: Hash) -> Self {
71 Self::copy_from_slice(h.as_ref())
72 }
73}
74
75impl TryFrom<Bytes> for Hash {
76 type Error = Error;
77
78 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
79 Self::from_bytes(Algorithm::Sha256, value.as_ref())
80 }
81}
82
83impl Hash {
84 pub fn from_bytes(alg: Algorithm, bytes: &[u8]) -> Result<Hash, Error> {
86 if bytes.is_empty() {
87 return Ok(Hash::None);
88 }
89 match alg {
90 Algorithm::Sha256 => {
91 if bytes.len() == SHA256_HASH_SIZE {
92 let mut h = [0u8; SHA256_HASH_SIZE];
93 h.copy_from_slice(bytes);
94 Ok(Hash::Sha256(h))
95 } else {
96 Err(Error::invalid_hash_size())
97 }
98 },
99 }
100 }
101
102 pub fn from_hex_upper(alg: Algorithm, s: &str) -> Result<Hash, Error> {
104 if s.is_empty() {
105 return Ok(Hash::None);
106 }
107 match alg {
108 Algorithm::Sha256 => {
109 let mut h = [0u8; SHA256_HASH_SIZE];
110 Hex::upper_case()
111 .decode_to_slice(s.as_bytes(), &mut h)
112 .map_err(Error::subtle_encoding)?;
113 Ok(Hash::Sha256(h))
114 },
115 }
116 }
117
118 pub fn algorithm(self) -> Algorithm {
120 match self {
121 Hash::Sha256(_) => Algorithm::Sha256,
122 Hash::None => Algorithm::Sha256,
123 }
124 }
125
126 pub fn as_bytes(&self) -> &[u8] {
128 match self {
129 Hash::Sha256(ref h) => h.as_ref(),
130 Hash::None => &[],
131 }
132 }
133
134 pub fn is_empty(&self) -> bool {
136 self == &Hash::None
137 }
138}
139
140impl Debug for Hash {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 match self {
143 Hash::Sha256(_) => write!(f, "Hash::Sha256({self})"),
144 Hash::None => write!(f, "Hash::None"),
145 }
146 }
147}
148
149impl Display for Hash {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 let hex = match self {
152 Hash::Sha256(ref h) => Hex::upper_case().encode_to_string(h).unwrap(),
153 Hash::None => String::new(),
154 };
155
156 write!(f, "{hex}")
157 }
158}
159
160impl FromStr for Hash {
161 type Err = Error;
162
163 fn from_str(s: &str) -> Result<Self, Error> {
164 Self::from_hex_upper(Algorithm::Sha256, s)
165 }
166}
167
168impl<'de> Deserialize<'de> for Hash {
169 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
170 let hex = CowStr::deserialize(deserializer)?;
171
172 if hex.is_empty() {
173 Ok(Hash::None)
174 } else {
175 Ok(Self::from_str(&hex).map_err(|e| D::Error::custom(format!("{e}")))?)
176 }
177 }
178}
179
180impl Serialize for Hash {
181 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
182 self.to_string().serialize(serializer)
183 }
184}
185
186pub mod allow_empty {
188 use super::*;
189
190 pub fn serialize<S>(value: &Hash, serializer: S) -> Result<S::Ok, S::Error>
192 where
193 S: Serializer,
194 {
195 value.to_string().serialize(serializer)
196 }
197
198 pub fn deserialize<'de, D>(deserializer: D) -> Result<Hash, D::Error>
201 where
202 D: Deserializer<'de>,
203 {
204 let hex = <&str>::deserialize(deserializer)?;
205 Hash::from_str(hex).map_err(serde::de::Error::custom)
206 }
207}
208
209#[derive(Clone, PartialEq, Eq, Default)]
211pub struct AppHash(Vec<u8>);
212
213impl Protobuf<Vec<u8>> for AppHash {}
214
215impl TryFrom<Vec<u8>> for AppHash {
216 type Error = Error;
217
218 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
219 Ok(AppHash(value))
220 }
221}
222impl From<AppHash> for Vec<u8> {
223 fn from(value: AppHash) -> Self {
224 value.0
225 }
226}
227
228impl TryFrom<Bytes> for AppHash {
229 type Error = Error;
230
231 fn try_from(value: Bytes) -> Result<Self, Self::Error> {
232 Ok(AppHash(value.to_vec()))
233 }
234}
235impl From<AppHash> for Bytes {
236 fn from(value: AppHash) -> Self {
237 value.0.into()
238 }
239}
240
241impl AppHash {
242 pub fn as_bytes(&self) -> &[u8] {
244 &self.0
245 }
246
247 pub fn from_hex_upper(s: &str) -> Result<Self, Error> {
249 if s.len() % 2 != 0 {
250 return Err(Error::invalid_app_hash_length());
251 }
252 let mut h = vec![0; s.len() / 2];
253 Hex::upper_case()
254 .decode_to_slice(s.as_bytes(), &mut h)
255 .map_err(Error::subtle_encoding)?;
256 Ok(AppHash(h))
257 }
258}
259
260impl AsRef<[u8]> for AppHash {
261 fn as_ref(&self) -> &[u8] {
262 self.0.as_ref()
263 }
264}
265
266impl Debug for AppHash {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 write!(
269 f,
270 "AppHash({})",
271 Hex::upper_case().encode_to_string(&self.0).unwrap()
272 )
273 }
274}
275
276impl Display for AppHash {
277 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278 write!(
279 f,
280 "{}",
281 Hex::upper_case().encode_to_string(&self.0).unwrap()
282 )
283 }
284}
285
286impl FromStr for AppHash {
287 type Err = Error;
288
289 fn from_str(s: &str) -> Result<Self, Error> {
290 Self::from_hex_upper(s)
291 }
292}