summaryrefslogtreecommitdiffstats
path: root/third_party/rust/rkv/examples
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/rkv/examples')
-rw-r--r--third_party/rust/rkv/examples/README.md11
-rw-r--r--third_party/rust/rkv/examples/iterator.rs76
-rw-r--r--third_party/rust/rkv/examples/simple-store.rs252
3 files changed, 339 insertions, 0 deletions
diff --git a/third_party/rust/rkv/examples/README.md b/third_party/rust/rkv/examples/README.md
new file mode 100644
index 0000000000..0e5a3e6d67
--- /dev/null
+++ b/third_party/rust/rkv/examples/README.md
@@ -0,0 +1,11 @@
+## Examples of how to use rkv
+
+All examples can be executed with:
+
+```
+cargo run --example $name
+```
+
+* [`simple-store`](simple-store.rs) - a simple key/value store that showcases the basic usage of rkv.
+
+* [`iterator`](iterator.rs) - a demo that showcases the basic usage of iterators in rkv.
diff --git a/third_party/rust/rkv/examples/iterator.rs b/third_party/rust/rkv/examples/iterator.rs
new file mode 100644
index 0000000000..445dc37c28
--- /dev/null
+++ b/third_party/rust/rkv/examples/iterator.rs
@@ -0,0 +1,76 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+//! A demo that showcases the basic usage of iterators in rkv.
+//!
+//! You can test this out by running:
+//!
+//! cargo run --example iterator
+
+use std::{fs, str};
+
+use tempfile::Builder;
+
+use rkv::{
+ backend::{SafeMode, SafeModeDatabase, SafeModeEnvironment},
+ Manager, Rkv, SingleStore, StoreError, StoreOptions, Value,
+};
+
+fn main() {
+ let root = Builder::new().prefix("iterator").tempdir().unwrap();
+ fs::create_dir_all(root.path()).unwrap();
+ let p = root.path();
+
+ let mut manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
+ let created_arc = manager.get_or_create(p, Rkv::new::<SafeMode>).unwrap();
+ let k = created_arc.read().unwrap();
+ let store = k.open_single("store", StoreOptions::create()).unwrap();
+
+ populate_store(&k, store).unwrap();
+
+ let reader = k.read().unwrap();
+
+ println!("Iterating from the beginning...");
+ // Reader::iter_start() iterates from the first item in the store, and
+ // returns the (key, value) tuples in order.
+ let mut iter = store.iter_start(&reader).unwrap();
+ while let Some(Ok((country, city))) = iter.next() {
+ let country = str::from_utf8(country).unwrap();
+ println!("{country}, {city:?}");
+ }
+
+ println!();
+ println!("Iterating from the given key...");
+ // Reader::iter_from() iterates from the first key equal to or greater
+ // than the given key.
+ let mut iter = store.iter_from(&reader, "Japan").unwrap();
+ while let Some(Ok((country, city))) = iter.next() {
+ println!("{}, {city:?}", str::from_utf8(country).unwrap());
+ }
+
+ println!();
+ println!("Iterating from the given prefix...");
+ let mut iter = store.iter_from(&reader, "Un").unwrap();
+ while let Some(Ok((country, city))) = iter.next() {
+ println!("{}, {city:?}", str::from_utf8(country).unwrap());
+ }
+}
+
+fn populate_store(
+ k: &Rkv<SafeModeEnvironment>,
+ store: SingleStore<SafeModeDatabase>,
+) -> Result<(), StoreError> {
+ let mut writer = k.write()?;
+ for (country, city) in vec![
+ ("Canada", Value::Str("Ottawa")),
+ ("United States of America", Value::Str("Washington")),
+ ("Germany", Value::Str("Berlin")),
+ ("France", Value::Str("Paris")),
+ ("Italy", Value::Str("Rome")),
+ ("United Kingdom", Value::Str("London")),
+ ("Japan", Value::Str("Tokyo")),
+ ] {
+ store.put(&mut writer, country, &city)?;
+ }
+ writer.commit()
+}
diff --git a/third_party/rust/rkv/examples/simple-store.rs b/third_party/rust/rkv/examples/simple-store.rs
new file mode 100644
index 0000000000..c097a2f573
--- /dev/null
+++ b/third_party/rust/rkv/examples/simple-store.rs
@@ -0,0 +1,252 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+//! A simple rkv demo that showcases the basic usage (put/get/delete) of rkv.
+//!
+//! You can test this out by running:
+//!
+//! cargo run --example simple-store
+
+use std::fs;
+
+use tempfile::Builder;
+
+use rkv::{
+ backend::{SafeMode, SafeModeDatabase, SafeModeEnvironment, SafeModeRwTransaction},
+ Manager, Rkv, StoreOptions, Value,
+};
+
+type MultiStore = rkv::MultiStore<SafeModeDatabase>;
+type Writer<'w> = rkv::Writer<SafeModeRwTransaction<'w>>;
+
+fn getput<'w, 's>(store: MultiStore, writer: &'w mut Writer, ids: &'s mut Vec<String>) {
+ let keys = vec!["str1", "str2", "str3"];
+ // we convert the writer into a cursor so that we can safely read
+ for k in keys.iter() {
+ // this is a multi-valued database, so get returns an iterator
+ let mut iter = store.get(writer, k).unwrap();
+ while let Some(Ok((_key, val))) = iter.next() {
+ if let Value::Str(s) = val {
+ ids.push(s.to_owned());
+ } else {
+ panic!("didn't get a string back!");
+ }
+ }
+ }
+ for id in ids {
+ store.put(writer, &id, &Value::Blob(b"weeeeeee")).unwrap();
+ }
+}
+
+fn delete(store: MultiStore, writer: &mut Writer) {
+ let keys = vec!["str1", "str2", "str3"];
+ let vals = vec!["string uno", "string quatro", "string siete"];
+ // we convert the writer into a cursor so that we can safely read
+ for i in 0..keys.len() {
+ store
+ .delete(writer, &keys[i], &Value::Str(vals[i]))
+ .unwrap();
+ }
+}
+
+fn main() {
+ let root = Builder::new().prefix("simple-db").tempdir().unwrap();
+ fs::create_dir_all(root.path()).unwrap();
+ let p = root.path();
+
+ // The manager enforces that each process opens the same lmdb environment at most once
+ let mut manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
+ let created_arc = manager.get_or_create(p, Rkv::new::<SafeMode>).unwrap();
+ let k = created_arc.read().unwrap();
+
+ // Creates a store called "store"
+ let store = k.open_single("store", StoreOptions::create()).unwrap();
+ let multistore = k.open_multi("multistore", StoreOptions::create()).unwrap();
+
+ println!("Inserting data...");
+ {
+ // Use a writer to mutate the store
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "int", &Value::I64(1234)).unwrap();
+ store
+ .put(&mut writer, "uint", &Value::U64(1234_u64))
+ .unwrap();
+ store
+ .put(&mut writer, "float", &Value::F64(1234.0.into()))
+ .unwrap();
+ store
+ .put(&mut writer, "instant", &Value::Instant(1_528_318_073_700))
+ .unwrap();
+ store
+ .put(&mut writer, "boolean", &Value::Bool(true))
+ .unwrap();
+ store
+ .put(&mut writer, "string", &Value::Str("héllo, yöu"))
+ .unwrap();
+ store
+ .put(
+ &mut writer,
+ "json",
+ &Value::Json(r#"{"foo":"bar", "number": 1}"#),
+ )
+ .unwrap();
+ store
+ .put(&mut writer, "blob", &Value::Blob(b"blob"))
+ .unwrap();
+ writer.commit().unwrap();
+ }
+
+ println!("Testing getput");
+ {
+ let mut ids = Vec::new();
+ let mut writer = k.write().unwrap();
+ multistore
+ .put(&mut writer, "str1", &Value::Str("string uno"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str1", &Value::Str("string dos"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str1", &Value::Str("string tres"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str2", &Value::Str("string quatro"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str2", &Value::Str("string cinco"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str2", &Value::Str("string seis"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str3", &Value::Str("string siete"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str3", &Value::Str("string ocho"))
+ .unwrap();
+ multistore
+ .put(&mut writer, "str3", &Value::Str("string nueve"))
+ .unwrap();
+ getput(multistore, &mut writer, &mut ids);
+ writer.commit().unwrap();
+ let mut writer = k.write().unwrap();
+ delete(multistore, &mut writer);
+ writer.commit().unwrap();
+ }
+
+ println!("Looking up keys...");
+ {
+ // Use a reader to query the store
+ let reader = k.read().unwrap();
+ println!("Get int {:?}", store.get(&reader, "int").unwrap());
+ println!("Get uint {:?}", store.get(&reader, "uint").unwrap());
+ println!("Get float {:?}", store.get(&reader, "float").unwrap());
+ println!("Get instant {:?}", store.get(&reader, "instant").unwrap());
+ println!("Get boolean {:?}", store.get(&reader, "boolean").unwrap());
+ println!("Get string {:?}", store.get(&reader, "string").unwrap());
+ println!("Get json {:?}", store.get(&reader, "json").unwrap());
+ println!("Get blob {:?}", store.get(&reader, "blob").unwrap());
+ println!(
+ "Get non-existent {:?}",
+ store.get(&reader, "non-existent").unwrap()
+ );
+ }
+
+ println!("Looking up keys via Writer.get()...");
+ {
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
+ store.put(&mut writer, "bar", &Value::Str("baz")).unwrap();
+ store.delete(&mut writer, "foo").unwrap();
+ println!(
+ "It should be None! ({:?})",
+ store.get(&writer, "foo").unwrap()
+ );
+ println!("Get bar ({:?})", store.get(&writer, "bar").unwrap());
+ writer.commit().unwrap();
+ let reader = k.read().expect("reader");
+ println!(
+ "It should be None! ({:?})",
+ store.get(&reader, "foo").unwrap()
+ );
+ println!("Get bar {:?}", store.get(&reader, "bar").unwrap());
+ }
+
+ println!("Aborting transaction...");
+ {
+ // Aborting a write transaction rollbacks the change(s)
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
+ writer.abort();
+
+ let reader = k.read().expect("reader");
+ println!(
+ "It should be None! ({:?})",
+ store.get(&reader, "foo").unwrap()
+ );
+ // Explicitly aborting a transaction is not required unless an early
+ // abort is desired, since both read and write transactions will
+ // implicitly be aborted once they go out of scope.
+ }
+
+ println!("Deleting keys...");
+ {
+ // Deleting a key/value also requires a write transaction
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
+ store.delete(&mut writer, "foo").unwrap();
+ println!(
+ "It should be None! ({:?})",
+ store.get(&writer, "foo").unwrap()
+ );
+ writer.commit().unwrap();
+
+ // Committing a transaction consumes the writer, preventing you
+ // from reusing it by failing and reporting a compile-time error.
+ // This line would report error[E0382]: use of moved value: `writer`.
+ // store.put(&mut writer, "baz", &Value::Str("buz")).unwrap();
+ }
+
+ println!("Clearing store...");
+ {
+ // Clearing a store deletes all the entries in that store
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
+ store.put(&mut writer, "bar", &Value::Str("baz")).unwrap();
+ store.clear(&mut writer).unwrap();
+ writer.commit().unwrap();
+
+ let reader = k.read().expect("reader");
+ println!(
+ "It should be None! ({:?})",
+ store.get(&reader, "foo").unwrap()
+ );
+ println!(
+ "It should be None! ({:?})",
+ store.get(&reader, "bar").unwrap()
+ );
+ }
+
+ println!("Write and read on multiple stores...");
+ {
+ let another_store = k
+ .open_single("another_store", StoreOptions::create())
+ .unwrap();
+ let mut writer = k.write().unwrap();
+ store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
+ another_store
+ .put(&mut writer, "foo", &Value::Str("baz"))
+ .unwrap();
+ writer.commit().unwrap();
+
+ let reader = k.read().unwrap();
+ println!(
+ "Get from store value: {:?}",
+ store.get(&reader, "foo").unwrap()
+ );
+ println!(
+ "Get from another store value: {:?}",
+ another_store.get(&reader, "foo").unwrap()
+ );
+ }
+}