holo_hash/
aliases.rs

1//! Type aliases for the various concrete HoloHash types
2
3use crate::hash_type;
4use crate::HashType;
5use crate::HoloHash;
6use crate::PrimitiveHashType;
7
8// NB: These could be macroized, but if we spell it out, we get better IDE
9// support
10
11// PRIMITIVE HASH TYPES
12
13/// An Agent public signing key. Not really a hash, more of an "identity hash".
14pub type AgentPubKey = HoloHash<hash_type::Agent>;
15
16/// A public key of a pair of signing keys for signing zome calls.
17pub type ZomeCallSigningKey = AgentPubKey;
18
19/// The hash of a DnaDef
20pub type DnaHash = HoloHash<hash_type::Dna>;
21
22/// The hash of a DhtOp's "unique form" representation
23pub type DhtOpHash = HoloHash<hash_type::DhtOp>;
24
25/// The hash of an Entry.
26pub type EntryHash = HoloHash<hash_type::Entry>;
27
28/// The hash of an action
29pub type ActionHash = HoloHash<hash_type::Action>;
30
31/// The hash of some wasm bytecode
32pub type WasmHash = HoloHash<hash_type::Wasm>;
33
34/// The hash of a Warrant
35pub type WarrantHash = HoloHash<hash_type::Warrant>;
36
37/// The hash of some external data that can't or doesn't exist on the DHT.
38pub type ExternalHash = HoloHash<hash_type::External>;
39
40// COMPOSITE HASH TYPES
41
42/// The hash of anything referrable in the DHT.
43/// This is a composite of either an EntryHash or a ActionHash
44pub type AnyDhtHash = HoloHash<hash_type::AnyDht>;
45
46/// The hash of anything linkable.
47pub type AnyLinkableHash = HoloHash<hash_type::AnyLinkable>;
48
49/// Alias for AnyLinkableHash. This hash forms the notion of the "basis hash" of an op.
50pub type OpBasis = AnyLinkableHash;
51
52/// The primitive hash types represented by this composite hash
53pub enum AnyDhtHashPrimitive {
54    /// This is an EntryHash
55    Entry(EntryHash),
56    /// This is a ActionHash
57    Action(ActionHash),
58}
59
60/// The primitive hash types represented by this composite hash
61pub enum AnyLinkableHashPrimitive {
62    /// This is an EntryHash
63    Entry(EntryHash),
64    /// This is a ActionHash
65    Action(ActionHash),
66    /// This is an ExternalHash
67    External(ExternalHash),
68}
69
70impl AnyLinkableHash {
71    /// Match on the primitive hash type represented by this composite hash type
72    pub fn into_primitive(self) -> AnyLinkableHashPrimitive {
73        match self.hash_type() {
74            hash_type::AnyLinkable::Entry => {
75                AnyLinkableHashPrimitive::Entry(self.retype(hash_type::Entry))
76            }
77            hash_type::AnyLinkable::Action => {
78                AnyLinkableHashPrimitive::Action(self.retype(hash_type::Action))
79            }
80            hash_type::AnyLinkable::External => {
81                AnyLinkableHashPrimitive::External(self.retype(hash_type::External))
82            }
83        }
84    }
85
86    /// Downcast to AnyDhtHash if this is not an external hash
87    pub fn into_any_dht_hash(self) -> Option<AnyDhtHash> {
88        match self.into_primitive() {
89            AnyLinkableHashPrimitive::Action(hash) => Some(AnyDhtHash::from(hash)),
90            AnyLinkableHashPrimitive::Entry(hash) => Some(AnyDhtHash::from(hash)),
91            AnyLinkableHashPrimitive::External(_) => None,
92        }
93    }
94
95    /// If this hash represents an ActionHash, return it, else None
96    pub fn into_action_hash(self) -> Option<ActionHash> {
97        if *self.hash_type() == hash_type::AnyLinkable::Action {
98            Some(self.retype(hash_type::Action))
99        } else {
100            None
101        }
102    }
103
104    /// If this hash represents an EntryHash, return it, else None
105    pub fn into_entry_hash(self) -> Option<EntryHash> {
106        if *self.hash_type() == hash_type::AnyLinkable::Entry {
107            Some(self.retype(hash_type::Entry))
108        } else {
109            None
110        }
111    }
112
113    /// If this hash represents an EntryHash which is actually an AgentPubKey,
114    /// return it, else None.
115    //
116    // NOTE: this is not completely correct since EntryHash should be a composite type,
117    //       with a fallible conversion to Agent
118    pub fn into_agent_pub_key(self) -> Option<AgentPubKey> {
119        if *self.hash_type() == hash_type::AnyLinkable::Entry {
120            Some(self.retype(hash_type::Agent))
121        } else {
122            None
123        }
124    }
125
126    /// If this hash represents an ExternalHash, return it, else None
127    pub fn into_external_hash(self) -> Option<ExternalHash> {
128        if *self.hash_type() == hash_type::AnyLinkable::External {
129            Some(self.retype(hash_type::External))
130        } else {
131            None
132        }
133    }
134}
135
136impl AnyDhtHash {
137    /// Match on the primitive hash type represented by this composite hash type
138    pub fn into_primitive(self) -> AnyDhtHashPrimitive {
139        match self.hash_type() {
140            hash_type::AnyDht::Entry => AnyDhtHashPrimitive::Entry(self.retype(hash_type::Entry)),
141            hash_type::AnyDht::Action => {
142                AnyDhtHashPrimitive::Action(self.retype(hash_type::Action))
143            }
144        }
145    }
146
147    /// If this hash represents an ActionHash, return it, else None
148    pub fn into_action_hash(self) -> Option<ActionHash> {
149        if *self.hash_type() == hash_type::AnyDht::Action {
150            Some(self.retype(hash_type::Action))
151        } else {
152            None
153        }
154    }
155
156    /// If this hash represents an EntryHash, return it, else None
157    pub fn into_entry_hash(self) -> Option<EntryHash> {
158        if *self.hash_type() == hash_type::AnyDht::Entry {
159            Some(self.retype(hash_type::Entry))
160        } else {
161            None
162        }
163    }
164
165    /// If this hash represents an EntryHash which is actually an AgentPubKey,
166    /// return it, else None.
167    //
168    // NOTE: this is not completely correct since EntryHash should be a composite type,
169    //       with a fallible conversion to Agent
170    pub fn into_agent_pub_key(self) -> Option<AgentPubKey> {
171        if *self.hash_type() == hash_type::AnyDht::Entry {
172            Some(self.retype(hash_type::Agent))
173        } else {
174            None
175        }
176    }
177}
178
179// We have From impls for:
180// - any primitive hash into a composite hash which contains that primitive
181// - any composite hash which is a subset of another composite hash (AnyDht < AnyLinkable)
182// - converting between EntryHash and AgentPubKey
183// All other conversions, viz. the inverses of the above, are TryFrom conversions, since to
184// go from a superset to a subset is only valid in certain cases.
185//
186// TODO: DRY up with macros
187
188// AnyDhtHash <-> AnyLinkableHash
189
190impl From<AnyDhtHash> for AnyLinkableHash {
191    fn from(hash: AnyDhtHash) -> Self {
192        let t = (*hash.hash_type()).into();
193        hash.retype(t)
194    }
195}
196
197impl TryFrom<AnyLinkableHash> for AnyDhtHash {
198    type Error = CompositeHashConversionError<hash_type::AnyLinkable>;
199
200    fn try_from(hash: AnyLinkableHash) -> Result<Self, Self::Error> {
201        hash.clone()
202            .into_any_dht_hash()
203            .ok_or_else(|| CompositeHashConversionError(hash, "AnyDht".into()))
204    }
205}
206
207// AnyDhtHash <-> primitives
208
209impl From<ActionHash> for AnyDhtHash {
210    fn from(hash: ActionHash) -> Self {
211        hash.retype(hash_type::AnyDht::Action)
212    }
213}
214
215impl From<EntryHash> for AnyDhtHash {
216    fn from(hash: EntryHash) -> Self {
217        hash.retype(hash_type::AnyDht::Entry)
218    }
219}
220
221// Since an AgentPubKey can be treated as an EntryHash, we can also go straight
222// to AnyDhtHash
223impl From<AgentPubKey> for AnyDhtHash {
224    fn from(hash: AgentPubKey) -> Self {
225        hash.retype(hash_type::AnyDht::Entry)
226    }
227}
228
229impl TryFrom<AnyDhtHash> for ActionHash {
230    type Error = HashConversionError<hash_type::AnyDht, hash_type::Action>;
231
232    fn try_from(hash: AnyDhtHash) -> Result<Self, Self::Error> {
233        hash.clone()
234            .into_action_hash()
235            .ok_or(HashConversionError(hash, hash_type::Action))
236    }
237}
238
239impl TryFrom<AnyDhtHash> for EntryHash {
240    type Error = HashConversionError<hash_type::AnyDht, hash_type::Entry>;
241
242    fn try_from(hash: AnyDhtHash) -> Result<Self, Self::Error> {
243        hash.clone()
244            .into_entry_hash()
245            .ok_or(HashConversionError(hash, hash_type::Entry))
246    }
247}
248
249// Since an AgentPubKey can be treated as an EntryHash, we can also go straight
250// from AnyDhtHash
251impl TryFrom<AnyDhtHash> for AgentPubKey {
252    type Error = HashConversionError<hash_type::AnyDht, hash_type::Agent>;
253
254    fn try_from(hash: AnyDhtHash) -> Result<Self, Self::Error> {
255        hash.clone()
256            .into_agent_pub_key()
257            .ok_or(HashConversionError(hash, hash_type::Agent))
258    }
259}
260
261// AnyLinkableHash <-> primitives
262
263impl From<ActionHash> for AnyLinkableHash {
264    fn from(hash: ActionHash) -> Self {
265        hash.retype(hash_type::AnyLinkable::Action)
266    }
267}
268
269impl From<EntryHash> for AnyLinkableHash {
270    fn from(hash: EntryHash) -> Self {
271        hash.retype(hash_type::AnyLinkable::Entry)
272    }
273}
274
275impl From<AgentPubKey> for AnyLinkableHash {
276    fn from(hash: AgentPubKey) -> Self {
277        hash.retype(hash_type::AnyLinkable::Entry)
278    }
279}
280
281impl From<ExternalHash> for AnyLinkableHash {
282    fn from(hash: ExternalHash) -> Self {
283        hash.retype(hash_type::AnyLinkable::External)
284    }
285}
286
287impl TryFrom<AnyLinkableHash> for ActionHash {
288    type Error = HashConversionError<hash_type::AnyLinkable, hash_type::Action>;
289
290    fn try_from(hash: AnyLinkableHash) -> Result<Self, Self::Error> {
291        hash.clone()
292            .into_action_hash()
293            .ok_or(HashConversionError(hash, hash_type::Action))
294    }
295}
296
297impl TryFrom<AnyLinkableHash> for EntryHash {
298    type Error = HashConversionError<hash_type::AnyLinkable, hash_type::Entry>;
299
300    fn try_from(hash: AnyLinkableHash) -> Result<Self, Self::Error> {
301        hash.clone()
302            .into_entry_hash()
303            .ok_or(HashConversionError(hash, hash_type::Entry))
304    }
305}
306
307// Since an AgentPubKey can be treated as an EntryHash, we can also go straight
308// from AnyLinkableHash
309impl TryFrom<AnyLinkableHash> for AgentPubKey {
310    type Error = HashConversionError<hash_type::AnyLinkable, hash_type::Agent>;
311
312    fn try_from(hash: AnyLinkableHash) -> Result<Self, Self::Error> {
313        hash.clone()
314            .into_agent_pub_key()
315            .ok_or(HashConversionError(hash, hash_type::Agent))
316    }
317}
318
319// Since an AgentPubKey can be treated as an EntryHash, we can also go straight
320// from AnyLinkableHash
321impl TryFrom<AnyLinkableHash> for ExternalHash {
322    type Error = HashConversionError<hash_type::AnyLinkable, hash_type::External>;
323
324    fn try_from(hash: AnyLinkableHash) -> Result<Self, Self::Error> {
325        hash.clone()
326            .into_external_hash()
327            .ok_or(HashConversionError(hash, hash_type::External))
328    }
329}
330
331#[cfg(feature = "serialization")]
332use holochain_serialized_bytes::prelude::*;
333
334/// A newtype for a collection of EntryHashes, needed for some wasm return types.
335#[cfg(feature = "serialization")]
336#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, SerializedBytes)]
337#[repr(transparent)]
338#[serde(transparent)]
339pub struct EntryHashes(pub Vec<EntryHash>);
340
341/// Error converting a composite hash into a primitive one, due to type mismatch
342#[derive(Debug, Clone, PartialEq, Eq)]
343pub struct HashConversionError<T: HashType, P: PrimitiveHashType>(HoloHash<T>, P);
344
345/// Error converting a composite hash into a subset composite hash, due to type mismatch
346#[derive(Debug, Clone, PartialEq, Eq)]
347pub struct CompositeHashConversionError<T: HashType>(HoloHash<T>, String);
348
349#[cfg(feature = "holochain-wasmer")]
350use holochain_wasmer_common::WasmErrorInner;
351
352#[cfg(feature = "holochain-wasmer")]
353impl<T: HashType, P: PrimitiveHashType> From<HashConversionError<T, P>> for WasmErrorInner {
354    fn from(err: HashConversionError<T, P>) -> Self {
355        WasmErrorInner::Guest(format!("{err:?}"))
356    }
357}
358
359#[cfg(feature = "holochain-wasmer")]
360impl<T: HashType> From<CompositeHashConversionError<T>> for WasmErrorInner {
361    fn from(err: CompositeHashConversionError<T>) -> Self {
362        WasmErrorInner::Guest(format!("{err:?}"))
363    }
364}