Skip to main content

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