rustica/pvec/mod.rs
1//! # Persistent Vector
2//!
3//! A persistent vector implementation using Relaxed Radix Balanced Trees (RRB-Trees).
4//!
5//! This data structure provides efficient immutable operations while
6//! maintaining structural sharing between versions. This makes it ideal
7//! for functional programming patterns and concurrent applications where
8//! immutable data structures are preferred.
9//!
10//! ## Key Features
11//!
12//! - **Immutability**: Each operation creates a new version without modifying the original
13//! - **Structural Sharing**: Minimizes memory usage by sharing unmodified subtrees
14//! - **Efficient Updates**: Log32 complexity for most operations
15//! - **Thread Safety**: Safe for concurrent access without locks
16//! - **Memory Efficiency**: Compact representation with optimizations for small vectors
17//!
18//! ## Performance Characteristics
19//!
20//! - **Access (get)**: O(log32 n) - virtually constant time for practical sizes
21//! - **Insert/Update**: O(log32 n)
22//! - **Push/Pop (at ends)**: O(1) amortized
23//! - **Slice**: O(log32 n)
24//! - **Concatenation**: O(log32 n)
25//! - **Split**: O(log32 n)
26//!
27//! ## When to Use Persistent Vector
28//!
29//! Persistent vectors are ideal for:
30//!
31//! - Maintaining history of changes (undo/redo functionality)
32//! - Concurrent programming without locks
33//! - Functional programming patterns requiring immutable data
34//! - Applications that need to compare or diff versions of collections
35//! - Scenarios where you need to provide a snapshot of data at a point in time
36//!
37//! ## Basic Usage
38//!
39//! ```rust
40//! use rustica::pvec;
41//! use rustica::pvec::PersistentVector;
42//!
43//! // Create a new vector using the pvec! macro
44//! let v1: PersistentVector<i32> = pvec![1, 2, 3, 4, 5];
45//!
46//! // Operations return new vectors, leaving the original unchanged
47//! let v2 = v1.push_back(6);
48//! let v3 = v1.update(0, 10);
49//!
50//! // Original vector remains unchanged
51//! assert_eq!(v1.get(0), Some(&1));
52//! assert_eq!(v1.len(), 5);
53//!
54//! // New vectors reflect the changes
55//! assert_eq!(v2.len(), 6);
56//! assert_eq!(v2.get(5), Some(&6));
57//!
58//! assert_eq!(v3.get(0), Some(&10));
59//! ```
60//!
61//! ## Advanced Examples
62//!
63//! ### Structural Sharing
64//!
65//! ```rust
66//! use rustica::pvec;
67//! use rustica::pvec::PersistentVector;
68//!
69//! // Create a large vector
70//! let mut large: PersistentVector<i32> = PersistentVector::new();
71//! for i in 0..1000 {
72//! large = large.push_back(i);
73//! }
74//!
75//! // Modify just one element
76//! let modified = large.update(500, 42);
77//!
78//! // Most of the internal structure is shared between the two vectors
79//! assert_eq!(large.get(500), Some(&500));
80//! assert_eq!(modified.get(500), Some(&42));
81//! ```
82//!
83//! ### Working with Slices and Splits
84//!
85//! ```rust
86//! use rustica::pvec;
87//! use rustica::pvec::PersistentVector;
88//!
89//! let vec: PersistentVector<char> = pvec!['a', 'b', 'c', 'd', 'e', 'f'];
90//!
91//! // Create a slice (this is a view, not a copy)
92//! let slice = vec.slice(1, 4);
93//! assert_eq!(slice.len(), 3);
94//! assert_eq!(slice.get(0), Some(&'b'));
95//! assert_eq!(slice.get(2), Some(&'d'));
96//!
97//! // Split a vector into two
98//! let (left, right) = vec.split_at(3);
99//! assert_eq!(left.len(), 3);
100//! assert_eq!(right.len(), 3);
101//! assert_eq!(left.get(0), Some(&'a'));
102//! assert_eq!(right.get(0), Some(&'d'));
103//! ```
104//!
105//! ### Thread-Safe Sharing with Arc
106//!
107//! ```rust
108//! use rustica::pvec;
109//! use rustica::pvec::PersistentVector;
110//! use std::sync::Arc;
111//! use std::thread;
112//!
113//! // Create a vector and convert it to Arc for thread-safe sharing
114//! let vec: PersistentVector<i32> = pvec![1, 2, 3, 4, 5];
115//! let arc_vec = vec.to_arc();
116//!
117//! // Spawn multiple threads that can safely access the same vector
118//! let handles: Vec<_> = (0..3)
119//! .map(|id| {
120//! let thread_vec = arc_vec.clone();
121//! thread::spawn(move || {
122//! // Each thread can safely read from the shared vector
123//! println!("Thread {}: Element at 0: {:?}", id, thread_vec.get(0));
124//!
125//! // Create a new version without affecting other threads
126//! let modified = thread_vec.update(0, id);
127//! (id, modified.get(0).cloned())
128//! })
129//! })
130//! .collect();
131//!
132//! // Wait for all threads to complete
133//! let results: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();
134//! for (id, value) in results {
135//! assert_eq!(value, Some(id));
136//! }
137//!
138//! // Original vector is still unchanged
139//! assert_eq!(arc_vec.get(0), Some(&1));
140//! ```
141//!
142//! ## Implementation Details
143//!
144//! The vector uses a combination of strategies for optimal performance:
145//!
146//! 1. **Optimized Small Vector**: Vectors with few elements use a compact representation
147//! 2. **RRB-Tree Structure**: Larger vectors use a tree with a branching factor of 32
148//! 3. **Efficient Memory Management**: Uses Arc for reference counting and structural sharing
149//! 4. **Path Caching**: Intelligent caching for faster sequential access
150//! 5. **Chunked Storage**: Elements are stored in fixed-size chunks for better cache locality
151//!
152//! ## Module Structure
153//!
154//! This module consists of several components:
155//!
156//! - **vector**: The main `PersistentVector` implementation (public API)
157//! - **iterator**: Various iterators for traversing the vector (public API)
158//! - **memory**: Memory management with reference counting (internal implementation)
159//! - **node**: Tree node implementation for the RRB-Tree (internal implementation)
160//! - **tree**: Core tree implementation with balancing algorithms (internal implementation)
161//! - **cache**: Path caching to accelerate repeated access patterns (internal implementation)
162//! - **chunk**: Efficient storage of elements in fixed-size arrays (internal implementation)
163//!
164//! Note that only the vector implementation and iterators are exposed as public API,
165//! while the internal implementation details are encapsulated to provide a clean
166//! and stable interface.
167
168// Submodules
169
170#[cfg(feature = "pvec")]
171pub(crate) mod memory;
172
173/// Iterators for traversing persistent vectors.
174#[cfg(feature = "pvec")]
175pub(crate) mod iterator;
176
177/// Tree node implementation for the RRB-Tree structure.
178#[cfg(feature = "pvec")]
179pub(crate) mod node;
180
181/// Core tree implementation with balancing algorithms.
182#[cfg(feature = "pvec")]
183pub(crate) mod tree;
184
185/// Main persistent vector implementation.
186#[cfg(feature = "pvec")]
187pub mod vector;
188
189// Re-exports of primary types
190
191/// The main persistent vector type.
192#[cfg(feature = "pvec")]
193pub use self::vector::PersistentVector;
194
195/// Custom memory manager for efficient allocation.
196#[cfg(feature = "pvec")]
197pub use self::memory::MemoryManager;
198
199// Iterator types
200#[cfg(feature = "pvec")]
201pub use self::iterator::{ChunksIter, IntoIter, Iter, SortedIter};
202
203/// Creates a new `PersistentVector` with the provided elements.
204///
205/// This macro provides a convenient way to create persistent vectors,
206/// similar to the standard library's `vec!` macro for `Vec`.
207#[macro_export]
208#[cfg(feature = "pvec")]
209macro_rules! pvec {
210 // Empty vector
211 () => { $crate::pvec::PersistentVector::new() };
212
213 // Vector with elements
214 ($($x:expr),*) => {{
215 let mut v = $crate::pvec::PersistentVector::new();
216 $(
217 v = v.push_back($x);
218 )*
219 v
220 }};
221
222 // Handle trailing comma case
223 ($($x:expr,)*) => { $crate::pvec![$($x),*] };
224}
225
226// Re-export the macro at the pvec module level
227pub use pvec;
228
229// Re-export cache policy types
230pub use crate::pvec::memory::AlwaysCache;
231pub use crate::pvec::memory::BoxedCachePolicy;
232pub use crate::pvec::memory::CachePolicy;
233pub use crate::pvec::memory::EvenIndexCache;
234pub use crate::pvec::memory::NeverCache;