Skip to main content

oxihuman_core/
array_stack.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 backed by a `Vec` with a maximum size.
6
7/// A stack with a fixed maximum capacity.
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct ArrayStack<T> {
11    data: Vec<T>,
12    capacity: usize,
13}
14
15#[allow(dead_code)]
16impl<T: Clone> ArrayStack<T> {
17    pub fn new(capacity: usize) -> Self {
18        Self {
19            data: Vec::with_capacity(capacity),
20            capacity,
21        }
22    }
23
24    pub fn push(&mut self, val: T) -> bool {
25        if self.data.len() >= self.capacity {
26            return false;
27        }
28        self.data.push(val);
29        true
30    }
31
32    pub fn pop(&mut self) -> Option<T> {
33        self.data.pop()
34    }
35
36    pub fn peek(&self) -> Option<&T> {
37        self.data.last()
38    }
39
40    pub fn len(&self) -> usize {
41        self.data.len()
42    }
43
44    pub fn is_empty(&self) -> bool {
45        self.data.is_empty()
46    }
47
48    pub fn is_full(&self) -> bool {
49        self.data.len() >= self.capacity
50    }
51
52    pub fn capacity(&self) -> usize {
53        self.capacity
54    }
55
56    pub fn clear(&mut self) {
57        self.data.clear();
58    }
59
60    pub fn remaining(&self) -> usize {
61        self.capacity - self.data.len()
62    }
63
64    pub fn as_slice(&self) -> &[T] {
65        &self.data
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn new_stack_is_empty() {
75        let s = ArrayStack::<i32>::new(4);
76        assert!(s.is_empty());
77        assert_eq!(s.len(), 0);
78    }
79
80    #[test]
81    fn push_and_pop() {
82        let mut s = ArrayStack::new(4);
83        assert!(s.push(10));
84        assert!(s.push(20));
85        assert_eq!(s.pop(), Some(20));
86        assert_eq!(s.pop(), Some(10));
87    }
88
89    #[test]
90    fn push_beyond_capacity_fails() {
91        let mut s = ArrayStack::new(2);
92        assert!(s.push(1));
93        assert!(s.push(2));
94        assert!(!s.push(3));
95    }
96
97    #[test]
98    fn peek_returns_top() {
99        let mut s = ArrayStack::new(4);
100        s.push(5);
101        s.push(10);
102        assert_eq!(s.peek(), Some(&10));
103    }
104
105    #[test]
106    fn is_full_at_capacity() {
107        let mut s = ArrayStack::new(1);
108        assert!(!s.is_full());
109        s.push(42);
110        assert!(s.is_full());
111    }
112
113    #[test]
114    fn clear_empties_stack() {
115        let mut s = ArrayStack::new(4);
116        s.push(1);
117        s.push(2);
118        s.clear();
119        assert!(s.is_empty());
120    }
121
122    #[test]
123    fn remaining_tracks_space() {
124        let mut s = ArrayStack::new(3);
125        assert_eq!(s.remaining(), 3);
126        s.push(1);
127        assert_eq!(s.remaining(), 2);
128    }
129
130    #[test]
131    fn as_slice_returns_data() {
132        let mut s = ArrayStack::new(4);
133        s.push(10);
134        s.push(20);
135        assert_eq!(s.as_slice(), &[10, 20]);
136    }
137
138    #[test]
139    fn pop_empty_returns_none() {
140        let mut s = ArrayStack::<i32>::new(4);
141        assert_eq!(s.pop(), None);
142    }
143
144    #[test]
145    fn capacity_returns_max() {
146        let s = ArrayStack::<i32>::new(7);
147        assert_eq!(s.capacity(), 7);
148    }
149}