hdi/hash_path/anchor.rs
1use crate::hash_path::path::Component;
2use crate::hash_path::path::Path;
3use holochain_wasmer_guest::*;
4
5/// This is the root of the [`Path`] tree.
6///
7/// Forms the entry point to all anchors so that agents can navigate down the tree from here.
8pub const ROOT: &[u8; 2] = &[0x00, 0x00];
9
10#[derive(PartialEq, SerializedBytes, serde::Serialize, serde::Deserialize, Debug, Clone)]
11/// An anchor can only be 1 or 2 levels deep as "type" and "text".
12///
13/// The second level is optional and the Strings use the standard [`TryInto`] for path [`Component`] internally.
14///
15/// __Anchors are required to be included in an application's [`entry_defs`](crate::prelude::entry_types)__ callback and so implement all the standard methods.
16/// Technically the [`Anchor`] entry definition is the [`Path`] definition.
17///
18/// e.g. `entry_defs![Anchor::entry_def()]`
19///
20/// The methods implemented on anchor follow the patterns that predate the Path module but `Path::from(&anchor)` is always possible to use the newer APIs.
21pub struct Anchor {
22 pub anchor_type: String,
23 pub anchor_text: Option<String>,
24}
25
26/// Anchors are just a special case of path, so we can move from anchor to path losslessly.
27/// We simply format the anchor structure into a string that works with the path string handling.
28impl From<&Anchor> for Path {
29 fn from(anchor: &Anchor) -> Self {
30 let mut components = vec![
31 Component::new(ROOT.to_vec()),
32 Component::from(anchor.anchor_type.as_bytes().to_vec()),
33 ];
34 if let Some(text) = anchor.anchor_text.as_ref() {
35 components.push(Component::from(text.as_bytes().to_vec()));
36 }
37 components.into()
38 }
39}
40
41#[cfg(test)]
42#[test]
43fn hash_path_root() {
44 assert_eq!(ROOT, &[0_u8, 0]);
45}
46
47#[cfg(test)]
48#[test]
49fn hash_path_anchor_path() {
50 let examples = [
51 (
52 "foo",
53 None,
54 Path::from(vec![
55 Component::from(vec![0, 0]),
56 Component::from(vec![102, 111, 111]),
57 ]),
58 ),
59 (
60 "foo",
61 Some("bar".to_string()),
62 Path::from(vec![
63 Component::from(vec![0, 0]),
64 Component::from(vec![102, 111, 111]),
65 Component::from(vec![98, 97, 114]),
66 ]),
67 ),
68 ];
69 for (atype, text, path) in examples {
70 assert_eq!(
71 path,
72 (&Anchor {
73 anchor_type: atype.to_string(),
74 anchor_text: text,
75 })
76 .into(),
77 );
78 }
79}