1use alloc::string::{String, ToString};
5use anyhow::Result;
6use core::{
7 any::Any,
8 cmp::Ordering,
9 fmt::Debug,
10 hash::{Hash, Hasher},
11 marker::PhantomData,
12};
13use gprimitives::H256;
14use parity_scale_codec::{Decode, Encode};
15use scale_info::TypeInfo;
16
17fn option_string<T: ToString>(value: &Option<T>) -> String {
18 value
19 .as_ref()
20 .map(|v| v.to_string())
21 .unwrap_or_else(|| "<none>".to_string())
22}
23
24fn shortname<T: Any>() -> &'static str {
25 core::any::type_name::<T>()
26 .split("::")
27 .last()
28 .expect("name is empty")
29}
30
31#[derive(Encode, Decode, TypeInfo, derive_more::Into, derive_more::Display)]
32#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
33#[cfg_attr(feature = "std", serde(transparent))]
34#[display("{hash}")]
35#[scale_info(skip_type_params(T))]
36pub struct HashOf<T: 'static> {
37 hash: H256,
38 #[into(ignore)]
39 #[codec(skip)]
40 #[cfg_attr(feature = "std", serde(skip))]
41 _phantom: PhantomData<T>,
42}
43
44impl<T> Debug for HashOf<T> {
45 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46 write!(f, "HashOf<{}>({:?})", shortname::<T>(), self.hash)
47 }
48}
49
50impl<T> PartialEq for HashOf<T> {
51 fn eq(&self, other: &Self) -> bool {
52 self.hash.eq(&other.hash)
53 }
54}
55
56impl<T> Eq for HashOf<T> {}
57
58impl<T> PartialOrd for HashOf<T> {
59 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
60 Some(self.cmp(other))
61 }
62}
63
64impl<T> Ord for HashOf<T> {
65 fn cmp(&self, other: &Self) -> Ordering {
66 self.hash.cmp(&other.hash)
67 }
68}
69
70impl<T> Clone for HashOf<T> {
71 fn clone(&self) -> Self {
72 *self
73 }
74}
75
76impl<T> Copy for HashOf<T> {}
77
78impl<T> Hash for HashOf<T> {
79 fn hash<H: Hasher>(&self, state: &mut H) {
80 self.hash.hash(state)
81 }
82}
83
84impl<T> AsRef<[u8]> for HashOf<T> {
85 fn as_ref(&self) -> &[u8] {
86 self.hash.as_ref()
87 }
88}
89
90impl<T> HashOf<T> {
91 pub unsafe fn new(hash: H256) -> Self {
94 Self {
95 hash,
96 _phantom: PhantomData,
97 }
98 }
99
100 pub fn inner(self) -> H256 {
102 self.hash
103 }
104
105 pub fn zero() -> Self {
106 Self {
107 hash: H256::zero(),
108 _phantom: PhantomData,
109 }
110 }
111
112 #[cfg(feature = "mock")]
113 pub fn random() -> Self {
114 Self {
115 hash: H256::random(),
116 _phantom: PhantomData,
117 }
118 }
119}
120
121impl<T> Default for HashOf<T> {
122 fn default() -> Self {
123 Self::zero()
124 }
125}
126
127#[derive(
128 Encode, Decode, PartialEq, Eq, derive_more::Into, derive_more::From, derive_more::Display,
129)]
130#[cfg_attr(
131 feature = "std",
132 derive(serde::Serialize, serde::Deserialize),
133 serde(bound = "")
134)]
135#[display("{}", option_string(_0))]
136pub struct MaybeHashOf<T: 'static>(Option<HashOf<T>>);
137
138impl<T> Debug for MaybeHashOf<T> {
139 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
140 let option_string = option_string(&Self::to_inner(*self).map(HashOf::inner));
141 write!(f, "MaybeHashOf<{}>({})", shortname::<T>(), option_string)
142 }
143}
144
145impl<T> Clone for MaybeHashOf<T> {
146 fn clone(&self) -> Self {
147 *self
148 }
149}
150
151impl<T> Copy for MaybeHashOf<T> {}
152
153impl<T> Hash for MaybeHashOf<T> {
154 fn hash<H: Hasher>(&self, state: &mut H) {
155 self.0.hash(state)
156 }
157}
158
159impl<T> MaybeHashOf<T> {
160 pub const fn empty() -> Self {
161 Self(None)
162 }
163
164 pub const fn is_empty(&self) -> bool {
165 self.0.is_none()
166 }
167
168 pub fn from_inner(inner: Option<HashOf<T>>) -> Self {
169 Self(inner)
170 }
171
172 pub fn to_inner(self) -> Option<HashOf<T>> {
173 self.0
174 }
175
176 pub fn map<U>(&self, f: impl FnOnce(HashOf<T>) -> U) -> Option<U> {
177 self.to_inner().map(f)
178 }
179
180 pub fn map_or_default<U: Default>(&self, f: impl FnOnce(HashOf<T>) -> U) -> U {
181 self.map(f).unwrap_or_default()
182 }
183
184 pub fn try_map_or_default<U: Default>(
185 &self,
186 f: impl FnOnce(HashOf<T>) -> Result<U>,
187 ) -> Result<U> {
188 self.map(f).unwrap_or_else(|| Ok(Default::default()))
189 }
190
191 pub fn replace(&mut self, other: Option<Self>) {
192 if let Some(other) = other {
193 *self = other;
194 }
195 }
196}
197
198impl<T> From<HashOf<T>> for MaybeHashOf<T> {
199 fn from(value: HashOf<T>) -> Self {
200 Self(Some(value))
201 }
202}