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"); }