microstack/
stack.rs

1// Copyright (c) 2023 Yegor Bugayenko
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included
11// in all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::Stack;
22
23impl<V: Copy, const N: usize> Stack<V, N> {
24    /// Make it from vector.
25    #[inline]
26    #[must_use]
27    pub fn from_vec(v: Vec<V>) -> Self {
28        let mut p = Self::new();
29        for i in v {
30            unsafe { p.push_unchecked(i) };
31        }
32        p
33    }
34
35    /// Get the capacity.
36    #[inline]
37    #[must_use]
38    pub fn capacity(&mut self) -> usize {
39        N
40    }
41
42    /// Push new element into it.
43    ///
44    /// # Safety
45    ///
46    /// It may lead to undefined behavior, if you go over the boundary.
47    #[inline]
48    pub unsafe fn push_unchecked(&mut self, v: V) {
49        self.items.as_mut_ptr().add(self.next).write(v);
50        self.next += 1;
51    }
52
53    /// Push new element into it.
54    ///
55    /// # Panics
56    ///
57    /// If there is no more space in the stack, it will panic.
58    #[inline]
59    pub fn push(&mut self, v: V) {
60        assert!(self.next < N, "No more space left in the stack");
61        unsafe {
62            self.push_unchecked(v);
63        }
64    }
65
66    /// Makes an attempt to push a new element into the stack.
67    ///
68    /// If there was enough space in the stack, `Ok(v)` is returned, while
69    /// `Err` is returned otherwise.
70    ///
71    /// # Errors
72    ///
73    /// If there is not enough space in the stack, `Err` is returned.
74    #[inline]
75    pub fn try_push(&mut self, v: V) -> Result<(), String> {
76        if self.next < N {
77            self.push(v);
78            Ok(())
79        } else {
80            Err(format!(
81                "There are no space left in the stack of {}",
82                self.capacity()
83            ))
84        }
85    }
86
87    /// Pop a element from it.
88    ///
89    /// # Safety
90    ///
91    /// If there are no items in the array, the result is undefined.
92    #[inline]
93    pub unsafe fn pop_unchecked(&mut self) -> V {
94        self.next -= 1;
95        self.items.as_ptr().add(self.next).read()
96    }
97
98    /// Pop a element from it.
99    ///
100    /// # Panics
101    ///
102    /// If there are no items in the array, it will panic.
103    #[inline]
104    pub fn pop(&mut self) -> V {
105        assert!(self.next > 0, "No more items left in the stack");
106        unsafe { self.pop_unchecked() }
107    }
108
109    /// Pop a element from it.
110    ///
111    /// # Errors
112    ///
113    /// If there is no more elements left, it will return `None`.
114    #[inline]
115    pub fn try_pop(&mut self) -> Result<V, String> {
116        if self.next == 0 {
117            Err(format!(
118                "There are no items left in the stack of {}",
119                self.capacity()
120            ))
121        } else {
122            Ok(self.pop())
123        }
124    }
125
126    /// Clear.
127    #[inline]
128    pub fn clear(&mut self) {
129        self.next = 0;
130    }
131
132    /// Is it empty.
133    #[inline]
134    #[must_use]
135    pub const fn is_empty(&self) -> bool {
136        self.len() == 0
137    }
138
139    /// Length of it.
140    #[inline]
141    #[must_use]
142    pub const fn len(&self) -> usize {
143        self.next
144    }
145}
146
147#[test]
148fn push_one() {
149    let mut s: Stack<u64, 1> = Stack::new();
150    unsafe { s.push_unchecked(42) };
151    assert_eq!(42, s.pop());
152}
153
154#[test]
155fn push_safely() {
156    let mut s: Stack<u64, 1> = Stack::new();
157    s.push(42);
158    assert_eq!(42, s.pop());
159}
160
161#[test]
162fn try_to_push() {
163    let mut s: Stack<u64, 1> = Stack::new();
164    assert!(s.try_push(42).is_ok());
165    assert!(s.try_push(16).is_err());
166    assert_eq!(42, s.pop());
167}
168
169#[test]
170fn push_after_clear() {
171    let mut s: Stack<u64, 1> = Stack::new();
172    unsafe { s.push_unchecked(42) };
173    s.clear();
174    s.push(16);
175    assert_eq!(16, s.pop());
176}
177
178#[test]
179fn build_from_vec() {
180    let mut s: Stack<u64, 1> = Stack::from_vec(vec![42]);
181    assert_eq!(42, s.pop());
182}
183
184#[test]
185fn pop_none() {
186    let mut s: Stack<u64, 1> = Stack::new();
187    assert_eq!(0, s.len());
188    assert!(s.is_empty());
189    assert!(s.try_pop().is_err());
190}
191
192#[test]
193fn read_capacity() {
194    let mut s: Stack<u64, 1> = Stack::new();
195    assert_eq!(1, s.capacity());
196}
197
198#[test]
199fn safely_pop() {
200    let mut s: Stack<u64, 1> = Stack::new();
201    s.push(42);
202    assert_eq!(42, s.try_pop().unwrap());
203}
204
205#[test]
206fn with_str() {
207    let mut s: Stack<&str, 1> = Stack::new();
208    s.push("Hello!");
209    assert_eq!("Hello!", s.pop());
210}
211
212#[test]
213#[should_panic]
214fn panic_on_empty_stack_push() {
215    let mut s: Stack<u64, 0> = Stack::new();
216    assert_eq!(0, s.len());
217    s.push(11);
218}
219
220#[test]
221#[should_panic]
222fn panic_on_empty_stack_pop() {
223    let mut s: Stack<u64, 0> = Stack::new();
224    assert_eq!(0, s.len());
225    s.pop();
226}
227
228#[test]
229fn push_and_pop() {
230    let mut s: Stack<u64, 16> = Stack::new();
231    s.push(42);
232    assert_eq!(42, s.pop());
233}