Skip to main content

oxihuman_core/
compact_vec.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5/// A compact vector that stores small arrays inline before spilling to heap.
6#[allow(dead_code)]
7#[derive(Debug, Clone)]
8pub struct CompactVec<T: Clone + Default> {
9    inline: [T; 4],
10    inline_len: usize,
11    overflow: Vec<T>,
12}
13
14#[allow(dead_code)]
15impl<T: Clone + Default + PartialEq> CompactVec<T> {
16    pub fn new() -> Self {
17        Self {
18            inline: Default::default(),
19            inline_len: 0,
20            overflow: Vec::new(),
21        }
22    }
23
24    pub fn push(&mut self, val: T) {
25        if self.inline_len < 4 {
26            self.inline[self.inline_len] = val;
27            self.inline_len += 1;
28        } else {
29            self.overflow.push(val);
30        }
31    }
32
33    pub fn pop(&mut self) -> Option<T> {
34        if let Some(v) = self.overflow.pop() {
35            return Some(v);
36        }
37        if self.inline_len > 0 {
38            self.inline_len -= 1;
39            let val = self.inline[self.inline_len].clone();
40            self.inline[self.inline_len] = T::default();
41            Some(val)
42        } else {
43            None
44        }
45    }
46
47    pub fn len(&self) -> usize {
48        self.inline_len + self.overflow.len()
49    }
50
51    pub fn is_empty(&self) -> bool {
52        self.inline_len == 0 && self.overflow.is_empty()
53    }
54
55    pub fn get(&self, index: usize) -> Option<&T> {
56        if index < self.inline_len {
57            Some(&self.inline[index])
58        } else {
59            self.overflow.get(index - self.inline_len)
60        }
61    }
62
63    pub fn is_inline(&self) -> bool {
64        self.overflow.is_empty()
65    }
66
67    pub fn clear(&mut self) {
68        for i in 0..self.inline_len {
69            self.inline[i] = T::default();
70        }
71        self.inline_len = 0;
72        self.overflow.clear();
73    }
74
75    pub fn contains(&self, val: &T) -> bool {
76        for i in 0..self.inline_len {
77            if &self.inline[i] == val {
78                return true;
79            }
80        }
81        self.overflow.contains(val)
82    }
83
84    pub fn to_vec(&self) -> Vec<T> {
85        let mut v = Vec::with_capacity(self.len());
86        for i in 0..self.inline_len {
87            v.push(self.inline[i].clone());
88        }
89        v.extend_from_slice(&self.overflow);
90        v
91    }
92}
93
94impl<T: Clone + Default + PartialEq> Default for CompactVec<T> {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn test_new() {
106        let v: CompactVec<i32> = CompactVec::new();
107        assert!(v.is_empty());
108        assert!(v.is_inline());
109    }
110
111    #[test]
112    fn test_push_inline() {
113        let mut v = CompactVec::new();
114        v.push(1);
115        v.push(2);
116        assert_eq!(v.len(), 2);
117        assert!(v.is_inline());
118    }
119
120    #[test]
121    fn test_push_overflow() {
122        let mut v = CompactVec::new();
123        for i in 0..6 {
124            v.push(i);
125        }
126        assert_eq!(v.len(), 6);
127        assert!(!v.is_inline());
128    }
129
130    #[test]
131    fn test_get() {
132        let mut v = CompactVec::new();
133        v.push(10);
134        v.push(20);
135        v.push(30);
136        v.push(40);
137        v.push(50);
138        assert_eq!(v.get(0), Some(&10));
139        assert_eq!(v.get(4), Some(&50));
140        assert_eq!(v.get(10), None);
141    }
142
143    #[test]
144    fn test_pop() {
145        let mut v = CompactVec::new();
146        v.push(1);
147        v.push(2);
148        assert_eq!(v.pop(), Some(2));
149        assert_eq!(v.pop(), Some(1));
150        assert_eq!(v.pop(), None);
151    }
152
153    #[test]
154    fn test_clear() {
155        let mut v = CompactVec::new();
156        v.push(1);
157        v.push(2);
158        v.push(3);
159        v.push(4);
160        v.push(5);
161        v.clear();
162        assert!(v.is_empty());
163    }
164
165    #[test]
166    fn test_contains() {
167        let mut v = CompactVec::new();
168        v.push(10);
169        v.push(20);
170        assert!(v.contains(&10));
171        assert!(!v.contains(&30));
172    }
173
174    #[test]
175    fn test_to_vec() {
176        let mut v = CompactVec::new();
177        v.push(1);
178        v.push(2);
179        v.push(3);
180        assert_eq!(v.to_vec(), vec![1, 2, 3]);
181    }
182
183    #[test]
184    fn test_pop_from_overflow() {
185        let mut v = CompactVec::new();
186        for i in 0..6 {
187            v.push(i);
188        }
189        assert_eq!(v.pop(), Some(5));
190        assert_eq!(v.len(), 5);
191    }
192
193    #[test]
194    fn test_default() {
195        let v: CompactVec<f32> = CompactVec::default();
196        assert!(v.is_empty());
197    }
198}