Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Value Access

Several traits provide access to values stored in the trie; the difference between them is the duration for which the value reference must be borrowed.

  • [ZipperValues] is avilable on most zipper types, and provides short-lived access to values.
  • [ZipperReadOnlyValues] is only available on zippers that cannot modify the trie, and privides access to the same values but with a lifetime that allows the zipper to be moved while the borrow is still active.
  • [ZipperReadOnlyConditionalValues] makes lifetime guarantees somewhere in the middle. It allows safe access and some amount of zipper movement, while ensuring it's impossible to modify or delete a value while it is actively borrowed.

ZipperValues

The [ZipperValues] trait provides most zippers with the ability to access values of type V at the focus position.

Basic Value Access

The [val] method returns an Option<&V> - Some containing a reference to the value if one exists at the focus, or None if the path exists but has no associated value.

The returned reference has the same lifetime as the method call, which means you many modify the zipper (e.g. move its focus) while the borrow is active. For longer-lived references, use [ZipperReadOnlyValues] and [ZipperReadOnlyConditionalValues].

ZipperReadOnlyValues

The [ZipperReadOnlyValues] trait provides the same value access as [ZipperValues] but with a lifetime parameter that is tied to the source of the value, irrespective of the zipper. The zipper may be modified or even dropped, and the borrow remains valid.

This trait is implemented on read-only zipper types where the underlying data structure's lifetime can be guaranteed, and will never be implemented alongside [ZipperWriting] on the same type.

ZipperReadOnlyConditionalValues

The [ZipperReadOnlyConditionalValues] trait provides an intermediate approach between [ZipperValues] and [ZipperReadOnlyValues]. It uses a witness object to ensure the underlying values remain intact, while still allowing zipper modification.

Witness-Based Access

The trait introduces a [witness] method that returns a [WitnessT] type, which acts as a proof that the underlying data remains valid. The [get_val_with_witness] method then provides a reference with the witness's lifetime rather than relying on a borrow from the zipper.

This design allows the zipper to be moved while ensuring that any borrowed values remain valid as long as the witness remains active.

Example Usage

#![allow(unused)]
fn main() {
extern crate pathmap;
use pathmap::{PathMap, zipper::*};

// Create a PathMap and populate it
let mut map = PathMap::new();
map.insert(b"hello", "world");
map.insert(b"hello/nested", "value");

// Convert to a read-only zipper
let mut zipper = map.into_read_zipper(b"");

// Move to a position with a value
zipper.descend_to(b"hello");
assert!(zipper.is_val());

// Create a witness to enable extended lifetime access
let witness = zipper.witness();

// Get a reference using the witness
let value_ref = zipper.get_val_with_witness(&witness).unwrap();

// The zipper can now be moved while the value reference remains valid
zipper.descend_to(b"/nested");
assert!(zipper.is_val());

// The original value reference is still valid because the witness is alive
assert_eq!(*value_ref, "world");

// Get another value using the same witness
let nested_ref = zipper.get_val_with_witness(&witness).unwrap();
assert_eq!(*nested_ref, "value");

// Both references remain valid until the witness is dropped, even after the
// zipper is dropped
drop(zipper);
assert_eq!(*value_ref, "world");
assert_eq!(*nested_ref, "value");
}