Skip to main content

oxihuman_core/
fixed_array.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Fixed-capacity stack-allocated array with runtime length tracking.
6
7/// Fixed-capacity array with runtime length up to CAP.
8#[derive(Debug, Clone)]
9#[allow(dead_code)]
10pub struct FixedArray<T: Copy + Default, const CAP: usize> {
11    data: [T; CAP],
12    len: usize,
13}
14
15impl<T: Copy + Default, const CAP: usize> FixedArray<T, CAP> {
16    /// Create an empty FixedArray.
17    #[allow(dead_code)]
18    pub fn new() -> Self {
19        Self {
20            data: [T::default(); CAP],
21            len: 0,
22        }
23    }
24
25    /// Push a value; returns false if full.
26    #[allow(dead_code)]
27    pub fn push(&mut self, val: T) -> bool {
28        if self.len >= CAP {
29            return false;
30        }
31        self.data[self.len] = val;
32        self.len += 1;
33        true
34    }
35
36    /// Pop the last value.
37    #[allow(dead_code)]
38    pub fn pop(&mut self) -> Option<T> {
39        if self.len == 0 {
40            return None;
41        }
42        self.len -= 1;
43        Some(self.data[self.len])
44    }
45
46    /// Current length.
47    #[allow(dead_code)]
48    pub fn len(&self) -> usize {
49        self.len
50    }
51
52    /// Whether empty.
53    #[allow(dead_code)]
54    pub fn is_empty(&self) -> bool {
55        self.len == 0
56    }
57
58    /// Whether at capacity.
59    #[allow(dead_code)]
60    pub fn is_full(&self) -> bool {
61        self.len >= CAP
62    }
63
64    /// Capacity.
65    #[allow(dead_code)]
66    pub fn capacity(&self) -> usize {
67        CAP
68    }
69
70    /// Get element at index.
71    #[allow(dead_code)]
72    pub fn get(&self, idx: usize) -> Option<T> {
73        if idx < self.len {
74            Some(self.data[idx])
75        } else {
76            None
77        }
78    }
79
80    /// Set element at index; returns false if out of bounds.
81    #[allow(dead_code)]
82    pub fn set(&mut self, idx: usize, val: T) -> bool {
83        if idx < self.len {
84            self.data[idx] = val;
85            true
86        } else {
87            false
88        }
89    }
90
91    /// Clear all elements.
92    #[allow(dead_code)]
93    pub fn clear(&mut self) {
94        self.len = 0;
95    }
96
97    /// Slice of active elements.
98    #[allow(dead_code)]
99    pub fn as_slice(&self) -> &[T] {
100        &self.data[..self.len]
101    }
102
103    /// Swap two elements by index.
104    #[allow(dead_code)]
105    pub fn swap(&mut self, a: usize, b: usize) -> bool {
106        if a < self.len && b < self.len {
107            self.data.swap(a, b);
108            true
109        } else {
110            false
111        }
112    }
113}
114
115impl<T: Copy + Default, const CAP: usize> Default for FixedArray<T, CAP> {
116    fn default() -> Self {
117        Self::new()
118    }
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124
125    #[test]
126    fn test_push_pop() {
127        let mut fa: FixedArray<i32, 4> = FixedArray::new();
128        assert!(fa.push(10));
129        assert!(fa.push(20));
130        assert_eq!(fa.pop(), Some(20));
131        assert_eq!(fa.len(), 1);
132    }
133
134    #[test]
135    fn test_full() {
136        let mut fa: FixedArray<u8, 2> = FixedArray::new();
137        assert!(fa.push(1));
138        assert!(fa.push(2));
139        assert!(!fa.push(3));
140        assert!(fa.is_full());
141    }
142
143    #[test]
144    fn test_empty_pop() {
145        let mut fa: FixedArray<u8, 4> = FixedArray::new();
146        assert_eq!(fa.pop(), None);
147    }
148
149    #[test]
150    fn test_get_set() {
151        let mut fa: FixedArray<u32, 4> = FixedArray::new();
152        fa.push(5);
153        assert_eq!(fa.get(0), Some(5));
154        fa.set(0, 99);
155        assert_eq!(fa.get(0), Some(99));
156    }
157
158    #[test]
159    fn test_out_of_bounds() {
160        let fa: FixedArray<u32, 4> = FixedArray::new();
161        assert_eq!(fa.get(0), None);
162    }
163
164    #[test]
165    fn test_clear() {
166        let mut fa: FixedArray<i32, 4> = FixedArray::new();
167        fa.push(1);
168        fa.push(2);
169        fa.clear();
170        assert!(fa.is_empty());
171    }
172
173    #[test]
174    fn test_as_slice() {
175        let mut fa: FixedArray<i32, 8> = FixedArray::new();
176        fa.push(3);
177        fa.push(7);
178        assert_eq!(fa.as_slice(), &[3, 7]);
179    }
180
181    #[test]
182    fn test_swap() {
183        let mut fa: FixedArray<i32, 4> = FixedArray::new();
184        fa.push(1);
185        fa.push(2);
186        fa.swap(0, 1);
187        assert_eq!(fa.get(0), Some(2));
188        assert_eq!(fa.get(1), Some(1));
189    }
190
191    #[test]
192    fn test_capacity() {
193        let fa: FixedArray<f32, 16> = FixedArray::new();
194        assert_eq!(fa.capacity(), 16);
195    }
196}