Skip to content

Commit 047b67c

Browse files
committed
examples/
modified: Cargo.lock modified: Cargo.toml new file: examples/disk.rs new file: examples/memory.rs new file: examples/template.rs
1 parent b00da10 commit 047b67c

File tree

5 files changed

+275
-0
lines changed

5 files changed

+275
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ oorandom = "11.1.3"
7474
random-access-storage = "5.0.0"
7575
random-access-disk = { version = "3.0.0", default-features = false }
7676
random-access-memory = "3.0.0"
77+
tempfile = "3.8.1"
7778

7879
[dev-dependencies]
7980
async-std = { version = "1.12.0", features = ["attributes", "unstable"] }

examples/disk.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#[cfg(feature = "async-std")]
2+
use async_std::main as async_main;
3+
use hypercore::{HypercoreBuilder, HypercoreError, Storage};
4+
use tempfile::Builder;
5+
#[cfg(feature = "tokio")]
6+
use tokio::main as async_main;
7+
8+
/// Example about using an in-memory hypercore.
9+
#[async_main]
10+
async fn main() {
11+
12+
// For the purposes of this example, first create a
13+
// temporary directory to hold hypercore.
14+
let dir = Builder::new()
15+
.prefix("gnostr")
16+
.tempdir()
17+
.unwrap()
18+
.into_path();
19+
20+
println!(
21+
"{}",
22+
dir.display());
23+
24+
// Create a disk storage, overwriting existing values.
25+
let overwrite = true;
26+
let storage = Storage::new_disk(&dir, overwrite)
27+
.await
28+
.expect("Could not create disk storage");
29+
30+
// Build a new disk hypercore
31+
let mut hypercore = HypercoreBuilder::new(storage)
32+
.build()
33+
.await
34+
.expect("Could not create disk hypercore");
35+
36+
// Append values to the hypercore
37+
hypercore.append(b"Hello, ").await.unwrap();
38+
hypercore.append(b"from ").await.unwrap();
39+
40+
// Close hypercore
41+
drop(hypercore);
42+
43+
// Open hypercore again from same directory, not
44+
// overwriting.
45+
let overwrite = false;
46+
let storage = Storage::new_disk(&dir, overwrite)
47+
.await
48+
.expect("Could not open existing disk storage");
49+
let mut hypercore = HypercoreBuilder::new(storage)
50+
.open(true)
51+
.build()
52+
.await
53+
.expect("Could not open disk hypercore");
54+
55+
// Append new values to the hypercore
56+
hypercore.append(b" disk hypercore!").await.unwrap();
57+
58+
// Add three values and clear the first two
59+
let batch: &[&[u8]] = &[
60+
b"first value to clear",
61+
b"second value to clear",
62+
b"third value to keep",
63+
];
64+
let new_length = hypercore.append_batch(batch).await.unwrap().length;
65+
hypercore
66+
.clear(new_length - 3, new_length - 1)
67+
.await
68+
.unwrap();
69+
70+
// The two values return None, but the last one returns correctly
71+
assert!(hypercore.get(3).await.unwrap().is_none());
72+
assert!(hypercore.get(4).await.unwrap().is_none());
73+
assert_eq!(
74+
hypercore.get(5).await.unwrap().unwrap(),
75+
b"third value to keep"
76+
);
77+
78+
// Print the first three values, converting binary back to string
79+
println!(
80+
"{}{}{}",
81+
format_res(hypercore.get(0).await),
82+
format_res(hypercore.get(1).await),
83+
format_res(hypercore.get(2).await)
84+
); // prints "Hello, from disk hypercore!"
85+
}
86+
87+
fn format_res(res: Result<Option<Vec<u8>>, HypercoreError>) -> String {
88+
match res {
89+
Ok(Some(bytes)) => String::from_utf8(bytes).expect("Shouldn't fail in example"),
90+
Ok(None) => "Got None in feed".to_string(),
91+
Err(e) => format!("Error getting value from feed, reason = {e:?}"),
92+
}
93+
}

examples/memory.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#[cfg(feature = "async-std")]
2+
use async_std::main as async_main;
3+
use hypercore::{HypercoreBuilder, HypercoreError, Storage};
4+
#[cfg(feature = "tokio")]
5+
use tokio::main as async_main;
6+
7+
/// Example about using an in-memory hypercore.
8+
#[async_main]
9+
async fn main() {
10+
// Create a memory storage
11+
let storage = Storage::new_memory()
12+
.await
13+
.expect("Could not create memory storage");
14+
15+
// Build hypercore
16+
let mut hypercore = HypercoreBuilder::new(storage)
17+
.build()
18+
.await
19+
.expect("Could not create memory hypercore");
20+
21+
// Append values
22+
hypercore.append(b"Hello, ").await.unwrap();
23+
hypercore.append(b"from memory hypercore!").await.unwrap();
24+
25+
// Add three values and clear the first two
26+
let batch: &[&[u8]] = &[
27+
b"first value to clear",
28+
b"second value to clear",
29+
b"third value to keep",
30+
];
31+
let new_length = hypercore.append_batch(batch).await.unwrap().length;
32+
hypercore
33+
.clear(new_length - 3, new_length - 1)
34+
.await
35+
.unwrap();
36+
37+
// The two values return None, but the last one returns correctly
38+
assert!(hypercore.get(2).await.unwrap().is_none());
39+
assert!(hypercore.get(3).await.unwrap().is_none());
40+
assert_eq!(
41+
hypercore.get(4).await.unwrap().unwrap(),
42+
b"third value to keep"
43+
);
44+
45+
// Print values, converting binary back to string
46+
println!(
47+
"{}{}",
48+
format_res(hypercore.get(0).await),
49+
format_res(hypercore.get(1).await)
50+
); // prints "Hello, from memory hypercore!"
51+
}
52+
53+
fn format_res(res: Result<Option<Vec<u8>>, HypercoreError>) -> String {
54+
match res {
55+
Ok(Some(bytes)) => String::from_utf8(bytes).expect("Shouldn't fail in example"),
56+
Ok(None) => "Got None in feed".to_string(),
57+
Err(e) => format!("Error getting value from feed, reason = {e:?}"),
58+
}
59+
}

examples/template.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#[cfg(feature = "async-std")]
2+
use async_std::main as async_main;
3+
use hypercore::{
4+
Hypercore, HypercoreBuilder, HypercoreError, PartialKeypair, RequestBlock, RequestUpgrade,
5+
Storage,
6+
};
7+
use random_access_disk::RandomAccessDisk;
8+
use random_access_memory::RandomAccessMemory;
9+
use tempfile::Builder;
10+
#[cfg(feature = "tokio")]
11+
use tokio::main as async_main;
12+
13+
/// Example on how to replicate a (disk) hypercore to another (memory) hypercore.
14+
/// NB: The replication functions used here are low-level, built for use in the wire
15+
/// protocol.
16+
#[async_main]
17+
async fn main() {
18+
// For the purposes of this example, first create a
19+
// temporary directory to hold hypercore.
20+
let dir = Builder::new()
21+
.prefix("examples_replication")
22+
.tempdir()
23+
.unwrap()
24+
.into_path();
25+
26+
println!(
27+
"{}",
28+
dir.display());
29+
30+
31+
// Create a disk storage, overwriting existing values.
32+
let overwrite = true;
33+
let storage = Storage::new_disk(&dir, overwrite)
34+
.await
35+
.expect("Could not create disk storage");
36+
37+
// Build a new disk hypercore
38+
let mut origin_hypercore = HypercoreBuilder::new(storage)
39+
.build()
40+
.await
41+
.expect("Could not create disk hypercore");
42+
43+
// Append values to the hypercore
44+
let batch: &[&[u8]] = &[b"Hello, ", b"from ", b"replicated ", b"hypercore!"];
45+
origin_hypercore.append_batch(batch).await.unwrap();
46+
47+
// Store the public key
48+
let origin_public_key = origin_hypercore.key_pair().public;
49+
50+
// Create a peer of the origin hypercore using the public key
51+
let mut replicated_hypercore = HypercoreBuilder::new(
52+
Storage::new_memory()
53+
.await
54+
.expect("Could not create memory storage"),
55+
)
56+
.key_pair(PartialKeypair {
57+
public: origin_public_key,
58+
secret: None,
59+
})
60+
.build()
61+
.await
62+
.expect("Could not create memory hypercore");
63+
64+
// Replicate the four values in random order
65+
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 3).await;
66+
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 0).await;
67+
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 2).await;
68+
replicate_index(&mut origin_hypercore, &mut replicated_hypercore, 1).await;
69+
70+
// Print values from replicated hypercore, converting binary back to string
71+
println!(
72+
"{}{}{}{}",
73+
format_res(replicated_hypercore.get(0).await),
74+
format_res(replicated_hypercore.get(1).await),
75+
format_res(replicated_hypercore.get(2).await),
76+
format_res(replicated_hypercore.get(3).await)
77+
); // prints "Hello, from replicated hypercore!"
78+
}
79+
80+
async fn replicate_index(
81+
origin_hypercore: &mut Hypercore<RandomAccessDisk>,
82+
replicated_hypercore: &mut Hypercore<RandomAccessMemory>,
83+
request_index: u64,
84+
) {
85+
let missing_nodes = origin_hypercore
86+
.missing_nodes(request_index)
87+
.await
88+
.expect("Could not get missing nodes");
89+
let upgrade_start = replicated_hypercore.info().contiguous_length;
90+
let upgrade_length = origin_hypercore.info().contiguous_length - upgrade_start;
91+
92+
let proof = origin_hypercore
93+
.create_proof(
94+
Some(RequestBlock {
95+
index: request_index,
96+
nodes: missing_nodes,
97+
}),
98+
None,
99+
None,
100+
Some(RequestUpgrade {
101+
start: upgrade_start,
102+
length: upgrade_length,
103+
}),
104+
)
105+
.await
106+
.expect("Creating proof error")
107+
.expect("Could not get proof");
108+
// Then the proof is verified and applied to the replicated party.
109+
assert!(replicated_hypercore
110+
.verify_and_apply_proof(&proof)
111+
.await
112+
.expect("Verifying and applying proof failed"));
113+
}
114+
115+
fn format_res(res: Result<Option<Vec<u8>>, HypercoreError>) -> String {
116+
match res {
117+
Ok(Some(bytes)) => String::from_utf8(bytes).expect("Shouldn't fail in example"),
118+
Ok(None) => "Got None in feed".to_string(),
119+
Err(e) => format!("Error getting value from feed, reason = {e:?}"),
120+
}
121+
}

0 commit comments

Comments
 (0)