Skip to main content

VerMap

Struct VerMap 

Source
pub struct VerMap<K, V> { /* private fields */ }
Expand description

A persistent, versioned, ordered key-value map.

VerMap provides Git-style version control for a typed key-value store: branching, committing, three-way merge, rollback, and garbage collection, all backed by a persistent B+ tree with copy-on-write structural sharing.

§Lifecycle

A typical workflow mirrors the Git mental model:

  1. CreateVerMap::new() gives you a map with a single main branch and an empty working state.
  2. Writeinsert / remove mutate the working state of a branch (analogous to editing files in a Git working directory).
  3. Commitcommit snapshots the current working state into an immutable Commit. Each commit records the B+ tree root, parent linkage, and a wall-clock timestamp.
  4. Branchcreate_branch forks a lightweight branch from any existing branch. The new branch shares all history via structural sharing — no data is copied.
  5. Mergemerge(source, target) performs a three-way merge. Deletion is treated as “assigning ∅”, so all conflicts are resolved uniformly: source wins — whether source wrote a new value or deleted the key.
  6. Rollbackrollback_to rewinds a branch to an earlier commit; discard throws away uncommitted changes.
  7. Historylog, get_at_commit, iter_at_commit let you inspect any historical snapshot.
  8. GCgc reclaims commits and B+ tree nodes that are no longer reachable from any live branch.

§Quick start

use vsdb::versioned::map::VerMap;
use vsdb::versioned::NO_COMMIT;
use vsdb::{vsdb_set_base_dir, vsdb_get_base_dir};
use std::fs;

let dir = format!("/tmp/vsdb_testing/{}", rand::random::<u128>());
vsdb_set_base_dir(&dir).unwrap();

let mut m: VerMap<u32, String> = VerMap::new();
let main = m.main_branch();

// 1. Write on the default "main" branch.
m.insert(main, &1, &"hello".into()).unwrap();
m.insert(main, &2, &"world".into()).unwrap();
let c1 = m.commit(main).unwrap();

// 2. Fork a feature branch from main.
let feat = m.create_branch("feature", main).unwrap();
m.insert(feat, &1, &"hi".into()).unwrap();
let c2 = m.commit(feat).unwrap();

// 3. Branches are isolated — main is unchanged.
assert_eq!(m.get(main, &1).unwrap(), Some("hello".into()));
assert_eq!(m.get(feat, &1).unwrap(), Some("hi".into()));

// 4. Merge feature → main (source wins on conflict).
m.merge(feat, main).unwrap();
assert_eq!(m.get(main, &1).unwrap(), Some("hi".into()));

// 5. Clean up: delete the feature branch and run GC.
m.delete_branch(feat).unwrap();
m.gc();

fs::remove_dir_all(&dir).unwrap();

Implementations§

Source§

impl<K, V> VerMap<K, V>

Source

pub fn new() -> Self

Creates a new, empty versioned map with a default main branch.

Equivalent to new_with_main("main").

Source

pub fn instance_id(&self) -> u64

Returns the unique instance ID of this VerMap.

Source

pub fn save_meta(&self) -> Result<u64>

Persists this instance’s metadata to disk so that it can be recovered later via from_meta.

Returns the instance_id that should be passed to from_meta.

Source

pub fn from_meta(instance_id: u64) -> Result<Self>

Recovers a VerMap instance from previously saved metadata.

The caller must ensure that the underlying VSDB database still contains the data referenced by this instance ID.

Source

pub fn new_with_main(name: &str) -> Self

Creates a new, empty versioned map whose initial branch has the given name (e.g. "genesis", "canonical").

The initial branch is automatically designated as the main branch and cannot be deleted until another branch is promoted via set_main_branch.

Source

pub fn main_branch(&self) -> BranchId

Returns the BranchId of the current main branch.

Source

pub fn set_main_branch(&mut self, branch: BranchId) -> Result<()>

Designates branch as the new main branch.

The previous main branch becomes an ordinary branch (deletable). The new main branch is protected from deletion.

Source

pub fn create_branch( &mut self, name: &str, source_branch: BranchId, ) -> Result<BranchId>

Creates a new branch forked from source_branch.

The new branch inherits both the committed head and the current working state (uncommitted changes, if any) of the source branch.

Source

pub fn delete_branch(&mut self, branch: BranchId) -> Result<()>

Deletes a branch and automatically cleans up orphaned commits.

Decrements the ref-count on the branch’s HEAD commit. If it reaches zero, the commit is hard-deleted and the decrement cascades to its parents.

B+ tree node reclamation requires a separate gc call (or happens automatically in VerMapWithProof::from_map).

Source

pub fn list_branches(&self) -> Vec<(BranchId, String)>

Lists all branches as (BranchId, name).

Source

pub fn branch_id(&self, name: &str) -> Option<BranchId>

Looks up a branch by name, returning its ID if it exists.

Source

pub fn branch_name(&self, branch: BranchId) -> Option<String>

Returns the name of a branch given its ID.

Source

pub fn has_uncommitted(&self, branch: BranchId) -> Result<bool>

Returns true if the branch has uncommitted changes (dirty state differs from the head commit’s snapshot).

Source

pub fn get(&self, branch: BranchId, key: &K) -> Result<Option<V>>

Reads a value from the working state of branch.

Source

pub fn get_at_commit(&self, commit_id: CommitId, key: &K) -> Result<Option<V>>

Reads a value at a specific historical commit.

Source

pub fn contains_key(&self, branch: BranchId, key: &K) -> Result<bool>

Checks if key exists in the working state of branch.

Source

pub fn iter( &self, branch: BranchId, ) -> Result<impl Iterator<Item = (K, V)> + '_>

Iterates all entries on branch in ascending key order.

Source

pub fn range( &self, branch: BranchId, lo: Bound<&K>, hi: Bound<&K>, ) -> Result<impl Iterator<Item = (K, V)> + '_>

Iterates entries in [lo, hi) on branch in ascending key order.

Source

pub fn iter_at_commit( &self, commit_id: CommitId, ) -> Result<impl Iterator<Item = (K, V)> + '_>

Iterates all entries at a specific historical commit.

Source

pub fn range_at_commit( &self, commit_id: CommitId, lo: Bound<&K>, hi: Bound<&K>, ) -> Result<impl Iterator<Item = (K, V)> + '_>

Iterates entries in [lo, hi) at a specific historical commit in ascending key order.

Source

pub fn raw_iter( &self, branch: BranchId, ) -> Result<impl Iterator<Item = (Vec<u8>, Vec<u8>)> + '_>

Iterates all raw (untyped) key-value pairs on a branch.

Returns (Vec<u8>, Vec<u8>) without decoding, useful for feeding into external consumers (e.g. MPT hash computation).

Source

pub fn raw_iter_at_commit( &self, commit_id: CommitId, ) -> Result<impl Iterator<Item = (Vec<u8>, Vec<u8>)> + '_>

Iterates all raw (untyped) key-value pairs at a historical commit.

Source

pub fn contains_key_at_commit( &self, commit_id: CommitId, key: &K, ) -> Result<bool>

Checks if key exists at a specific historical commit.

Source

pub fn insert(&mut self, branch: BranchId, key: &K, value: &V) -> Result<()>

Inserts a key-value pair into the working state of branch.

Source

pub fn remove(&mut self, branch: BranchId, key: &K) -> Result<()>

Removes a key from the working state of branch.

Source

pub fn commit(&mut self, branch: BranchId) -> Result<CommitId>

Commits the current working state of branch, creating a new immutable Commit. Returns the commit ID.

Source

pub fn discard(&mut self, branch: BranchId) -> Result<()>

Discards uncommitted changes, resetting the working state to the branch head.

Source

pub fn rollback_to(&mut self, branch: BranchId, target: CommitId) -> Result<()>

Rolls back branch to a previous commit, discarding all commits after target on this branch.

target must be an ancestor of the branch’s current head. The discarded commits are not deleted (they may be reachable from other branches). Call gc to reclaim them.

Source

pub fn merge(&mut self, source: BranchId, target: BranchId) -> Result<CommitId>

Merges source branch into target branch using three-way merge.

Both branches must be committed (no uncommitted changes).

§Conflict resolution: source wins on conflicts

First, non-conflicting single-sided changes are preserved using the ancestor snapshot. If both sides changed the same key differently, source wins. A deletion is treated as “assigning ∅”, so delete-vs-modify is also resolved by source priority.

sourcetargetresult
unchanged (A)changed to TT (target-only change preserved)
changed to Sunchanged (A)S (source-only change preserved)
changed to Schanged to TS (conflict → source wins)
deleted (∅)changed to T (conflict → source wins → delete)
changed to Sdeleted (∅)S (conflict → source wins → keep)

The caller controls priority by choosing which branch to pass as source vs target.

If target has no commits, performs a fast-forward (no merge commit is created). Otherwise creates a merge commit on target with two parents.

Source

pub fn fork_point(&self, a: CommitId, b: CommitId) -> Option<CommitId>

Returns the lowest common ancestor (fork point) of two commits.

Useful for blockchain scenarios: given two chain tips, this finds the block where they diverged. Returns None only if the two commits share no common history.

Source

pub fn commit_distance(&self, from: CommitId, ancestor: CommitId) -> Option<u64>

Counts the number of first-parent commits between from and ancestor (exclusive).

Walks the first-parent chain starting at from until ancestor is reached. Returns None if ancestor is not a first-parent ancestor of from.

§Example — comparing fork lengths
let lca = map.fork_point(tip_a, tip_b).unwrap();
let ahead_a = map.commit_distance(tip_a, lca).unwrap();
let ahead_b = map.commit_distance(tip_b, lca).unwrap();
// The longer fork wins.
Source

pub fn get_commit(&self, commit_id: CommitId) -> Option<Commit>

Retrieves a commit by its ID.

Source

pub fn head_commit(&self, branch: BranchId) -> Result<Option<Commit>>

Returns the commit at the head of branch.

Source

pub fn log(&self, branch: BranchId) -> Result<Vec<Commit>>

Walks the first-parent commit history of branch from head to root.

For merge commits, only the first parent (the target branch at merge time) is followed — analogous to git log --first-parent.

Source

pub fn diff_commits( &self, from: CommitId, to: CommitId, ) -> Result<Vec<DiffEntry>>

Computes the diff between two commits.

Returns a list of DiffEntry in ascending key order, describing every key that was added, removed, or modified between from and to.

Source

pub fn diff_uncommitted(&self, branch: BranchId) -> Result<Vec<DiffEntry>>

Computes the diff of uncommitted (working) changes on branch.

Analogous to git diff (unstaged changes relative to HEAD).

Source

pub fn gc(&mut self)

Reclaims B+ tree nodes that are no longer reachable.

Commit lifecycle is handled automatically by reference counting (see delete_branch, rollback_to). This method performs:

  1. Crash recovery — if a ref-count cascade was interrupted, rebuilds all ref counts from scratch and removes orphaned commits.
  2. B+ tree sweep — mark-and-sweep over the node pool, keeping only nodes reachable from live commit roots and dirty (uncommitted) roots.

Trait Implementations§

Source§

impl<K: Clone, V: Clone> Clone for VerMap<K, V>

Source§

fn clone(&self) -> VerMap<K, V>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<K: Debug, V: Debug> Debug for VerMap<K, V>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<K, V> Default for VerMap<K, V>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de, K, V> Deserialize<'de> for VerMap<K, V>

Source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<K, V> Serialize for VerMap<K, V>

Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<K, V> !Freeze for VerMap<K, V>

§

impl<K, V> RefUnwindSafe for VerMap<K, V>

§

impl<K, V> Send for VerMap<K, V>
where K: Send, V: Send,

§

impl<K, V> Sync for VerMap<K, V>
where K: Sync, V: Sync,

§

impl<K, V> Unpin for VerMap<K, V>
where K: Unpin, V: Unpin,

§

impl<K, V> UnsafeUnpin for VerMap<K, V>

§

impl<K, V> UnwindSafe for VerMap<K, V>
where K: UnwindSafe, V: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> KeyDe for T

Source§

fn decode_key(bytes: &[u8]) -> Result<T, Box<dyn RucError>>

Decodes a key from a byte slice.
Source§

impl<T> KeyEn for T
where T: Serialize,

Source§

fn try_encode_key(&self) -> Result<Vec<u8>, Box<dyn RucError>>

Tries to encode the key into a byte vector.
Source§

fn encode_key(&self) -> RawBytes

Encodes the key into a byte vector, panicking on failure.
Source§

impl<T> KeyEnDe for T
where T: KeyEn + KeyDe,

Source§

fn try_encode(&self) -> Result<Vec<u8>, Box<dyn RucError>>

Tries to encode the key into a byte vector.
Source§

fn encode(&self) -> Vec<u8>

Encodes the key into a byte vector, panicking on failure.
Source§

fn decode(bytes: &[u8]) -> Result<T, Box<dyn RucError>>

Decodes a key from a byte slice.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> ValueDe for T

Source§

fn decode_value(bytes: &[u8]) -> Result<T, Box<dyn RucError>>

Decodes a value from a byte slice.
Source§

impl<T> ValueEn for T
where T: Serialize,

Source§

fn try_encode_value(&self) -> Result<Vec<u8>, Box<dyn RucError>>

Tries to encode the value into a byte vector.
Source§

fn encode_value(&self) -> RawBytes

Encodes the value into a byte vector, panicking on failure.
Source§

impl<T> ValueEnDe for T
where T: ValueEn + ValueDe,

Source§

fn try_encode(&self) -> Result<Vec<u8>, Box<dyn RucError>>

Tries to encode the value into a byte vector.
Source§

fn encode(&self) -> Vec<u8>

Encodes the value into a byte vector, panicking on failure.
Source§

fn decode(bytes: &[u8]) -> Result<T, Box<dyn RucError>>

Decodes a value from a byte slice.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,