Skip to main content

oxihuman_core/
persistent_vector.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Persistent vector stub — uses path-copying to produce new versions on
6//! each modification, keeping all prior versions intact.
7
8/// A version snapshot of the persistent vector.
9pub type PvecVersion = usize;
10
11/// Persistent vector that retains all historical versions.
12pub struct PersistentVector<T: Clone> {
13    versions: Vec<Vec<T>>,
14}
15
16impl<T: Clone> PersistentVector<T> {
17    /// Create an empty persistent vector.
18    pub fn new() -> Self {
19        Self {
20            versions: vec![Vec::new()],
21        }
22    }
23
24    /// Current (latest) version number.
25    pub fn current_version(&self) -> PvecVersion {
26        self.versions.len() - 1
27    }
28
29    /// Push `value` onto the current version, creating a new version.
30    pub fn push(&mut self, value: T) -> PvecVersion {
31        let mut next = self.versions.last().cloned().unwrap_or_default();
32        next.push(value);
33        self.versions.push(next);
34        self.current_version()
35    }
36
37    /// Pop the last element of the current version, creating a new version.
38    pub fn pop(&mut self) -> PvecVersion {
39        let mut next = self.versions.last().cloned().unwrap_or_default();
40        next.pop();
41        self.versions.push(next);
42        self.current_version()
43    }
44
45    /// Set element at `index` in the current version to `value`.
46    pub fn set(&mut self, index: usize, value: T) -> Option<PvecVersion> {
47        let len = self.versions.last().map_or(0, |v| v.len());
48        if index >= len {
49            return None;
50        }
51        let mut next = self.versions.last().cloned().unwrap_or_default();
52        next[index] = value;
53        self.versions.push(next);
54        Some(self.current_version())
55    }
56
57    /// Get element at `index` in the current version.
58    pub fn get(&self, index: usize) -> Option<&T> {
59        self.versions.last()?.get(index)
60    }
61
62    /// Get element at `index` in a specific `version`.
63    pub fn get_at(&self, version: PvecVersion, index: usize) -> Option<&T> {
64        self.versions.get(version)?.get(index)
65    }
66
67    /// Length of the current version.
68    pub fn len(&self) -> usize {
69        self.versions.last().map(|v| v.len()).unwrap_or(0)
70    }
71
72    /// True if current version is empty.
73    pub fn is_empty(&self) -> bool {
74        self.len() == 0
75    }
76
77    /// Total number of stored versions.
78    pub fn version_count(&self) -> usize {
79        self.versions.len()
80    }
81}
82
83impl<T: Clone> Default for PersistentVector<T> {
84    fn default() -> Self {
85        Self::new()
86    }
87}
88
89/// Create a new empty persistent vector.
90pub fn new_persistent_vector<T: Clone>() -> PersistentVector<T> {
91    PersistentVector::new()
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_push_and_get() {
100        let mut v: PersistentVector<i32> = PersistentVector::new();
101        v.push(10);
102        assert_eq!(v.get(0), Some(&10)); /* element accessible */
103    }
104
105    #[test]
106    fn test_old_version_preserved() {
107        let mut v: PersistentVector<i32> = PersistentVector::new();
108        v.push(1);
109        v.push(2);
110        assert_eq!(v.get_at(1, 0), Some(&1)); /* version 1 has one element */
111        assert_eq!(v.get_at(1, 1), None); /* version 1 lacks second */
112    }
113
114    #[test]
115    fn test_pop_creates_version() {
116        let mut v: PersistentVector<i32> = PersistentVector::new();
117        v.push(1);
118        let _vpush = v.push(2);
119        let vpop = v.pop();
120        assert_eq!(v.get_at(vpop, 1), None); /* element gone in new version */
121    }
122
123    #[test]
124    fn test_set() {
125        let mut v: PersistentVector<i32> = PersistentVector::new();
126        v.push(1);
127        let new_ver = v.set(0, 99).expect("should succeed");
128        assert_eq!(v.get_at(new_ver, 0), Some(&99)); /* updated */
129        assert_eq!(v.get_at(1, 0), Some(&1)); /* old version unchanged */
130    }
131
132    #[test]
133    fn test_set_out_of_bounds() {
134        let mut v: PersistentVector<i32> = PersistentVector::new();
135        assert!(v.set(5, 42).is_none()); /* out of bounds returns None */
136    }
137
138    #[test]
139    fn test_len() {
140        let mut v: PersistentVector<i32> = PersistentVector::new();
141        v.push(1);
142        v.push(2);
143        assert_eq!(v.len(), 2); /* correct length */
144    }
145
146    #[test]
147    fn test_is_empty() {
148        let v: PersistentVector<i32> = PersistentVector::new();
149        assert!(v.is_empty()); /* initially empty */
150    }
151
152    #[test]
153    fn test_version_count() {
154        let mut v: PersistentVector<i32> = PersistentVector::new();
155        v.push(1);
156        v.push(2);
157        assert_eq!(v.version_count(), 3); /* initial + 2 pushes */
158    }
159
160    #[test]
161    fn test_default() {
162        let v: PersistentVector<i32> = PersistentVector::default();
163        assert!(v.is_empty()); /* default is empty */
164    }
165
166    #[test]
167    fn test_new_helper() {
168        let v = new_persistent_vector::<u8>();
169        assert!(v.is_empty()); /* helper works */
170    }
171}