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