pushr/push/
stack.rs

1use std::fmt;
2
3#[derive(Clone, Debug)]
4pub struct PushStack<T> {
5    elements: Vec<T>,
6}
7
8pub trait PushPrint {
9    fn to_pstring(&self) -> String; 
10}
11
12impl PushPrint for f32 {
13    fn to_pstring(&self) -> String {
14        format!("{:.1}", self)
15    }
16}
17
18impl PushPrint for i32 {
19   fn to_pstring(&self) -> String {
20       self.to_string()
21   }
22}
23
24impl PushPrint for String {
25   fn to_pstring(&self) -> String {
26       self.to_string()
27   }
28}
29
30impl PushPrint for bool {
31   fn to_pstring(&self) -> String {
32       format!("{}", self.to_string().to_uppercase())
33   }
34}
35
36impl<T> PushStack<T>
37where
38    T: Clone + fmt::Display + PartialEq + PushPrint,
39{
40    pub fn new() -> Self {
41        Self {
42            elements: Vec::new(),
43        }
44    }
45
46    /// Initializes the stack with the argument. Its last
47    /// element becomes the top element of the stack.
48    pub fn from_vec(elements: Vec<T>) -> Self {
49        Self { elements: elements }
50    }
51
52    /// Prints the stack from top to bottom enumerating its elements.
53    pub fn to_string(&self) -> String {
54        let mut result = "".to_string();
55        for (_i, x) in self.elements.iter().rev().enumerate() {
56             result.push_str(&format!(" {}", x.to_pstring()));
57        }
58        result.trim().to_string()
59    }
60
61    /// Returns the stack size.
62    pub fn size(&self) -> usize {
63        return self.elements.len();
64    }
65
66    /// Returns true if the argument equals the
67    /// top element of the stack. Uses the = operator for
68    /// comparison (shallow for Items)
69    pub fn last_eq(&self, item: &T) -> bool {
70        return Some(item) == self.elements.last();
71    }
72
73    /// Returns true if the element at stack position i counting
74    /// from the top. Uses string representation for comparison
75    /// (deep)
76    pub fn equal_at(&self, i: usize, el: &T) -> Option<bool> {
77        if i > self.size() {
78            None
79        } else {
80            Some(self.elements[self.size() - (i + 1)].to_string() == *el.to_string())
81        }
82    }
83
84    /// Returns a mutable pointer to the element at the bottom
85    /// of the stack.
86    pub fn bottom_mut(&mut self) -> Option<&mut T> {
87        if self.size() > 0 {
88            self.elements.first_mut()
89        } else {
90            None
91        }
92    }
93
94    /// Removes all elements from the stack.
95    pub fn flush(&mut self) {
96        self.elements = Vec::new();
97    }
98
99    /// Replace element at position i counting from the top. In case the index does not
100    /// exist it returns the offset to the size of the stack wrapped in the Err enum.
101    pub fn replace(&mut self, i: usize, new_el: T) -> Result<(), usize> {
102        let size = &mut self.size();
103        match i.checked_sub(*size) {
104            None => {
105                let _ = std::mem::replace(&mut self.elements[*size - (i + 1)], new_el);
106                Ok(())
107            }
108            Some(diff) => Err(diff + 1),
109        }
110    }
111
112    /// Removes element at position i counting from the top.
113    pub fn remove(&mut self, i: usize) {
114        let size = self.size();
115        if i < size {
116            self.elements.remove(size - (i + 1));
117        }
118    }
119
120    /// Reverse elements of stack.
121    pub fn reverse(&mut self) {
122        self.elements.reverse();
123    }
124
125    /// Returns a mutable reference to the element at stack position i counting
126    /// from the top of the stack
127    pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
128        let size = &mut self.size();
129        if i < *size {
130            Some(&mut self.elements[*size - (i + 1)])
131        } else {
132            None
133        }
134    }
135
136    /// Returns a reference to the element at stack position i counting from the
137    /// top of the stack
138    pub fn get(&self, i: usize) -> Option<&T> {
139        let size = self.size();
140        if i < size {
141            Some(&self.elements[size - (i + 1)])
142        } else {
143            None
144        }
145    }
146
147    /// Pushes element to the top of the stack.
148    pub fn push(&mut self, value: T) {
149        self.elements.push(value);
150    }
151
152    /// Pushes element to the bottom of the stack.
153    pub fn push_front(&mut self, value: T) {
154        self.elements.insert(0, value);
155    }
156
157    /// Removes an indexed item from stack position i counting from the top and
158    /// pushes it on top of the stack.
159    pub fn yank(&mut self, index: usize) {
160        if index > 0 && index < self.size() {
161            let el = self.elements.remove(self.size() - (index + 1));
162            self.elements.push(el);
163        }
164    }
165
166    /// Removes the top element from the stack and inserts it at
167    /// position index counting from the top.
168    pub fn shove(&mut self, index: usize) {
169        if index > 0 && index < self.size() {
170            if let Some(el) = self.elements.pop() {
171                let top_down_index = self.size() - index;
172                self.elements.insert(top_down_index, el);
173            }
174        }
175    }
176
177    /// Swaps vector elements
178    pub fn swap(&mut self, i: usize, j: usize) {
179        self.elements.swap(i, j);
180    }
181
182    /// Removes the bottom element from the stack and returns it.
183    pub fn pop_front(&mut self) -> Option<T> {
184        if self.elements.is_empty() {
185            return None;
186        }
187        Some(self.elements.remove(0))
188    }
189
190    /// Removes the top element from the stack and returns it.
191    pub fn pop(&mut self) -> Option<T> {
192        self.elements.pop()
193    }
194
195    /// Pops and returns the n top-most elements of the stack.
196    /// The last element of the returned vector is the top
197    /// element of the stack.
198    pub fn pop_vec(&mut self, n: usize) -> Option<Vec<T>> {
199        if n > self.elements.len() {
200            None
201        } else {
202            Some(
203                self.elements
204                    .split_off(self.elements.len() - n)
205                    .into_iter()
206                    .collect(),
207            )
208        }
209    }
210
211    /// Returns a copy of the element at stack position i counting
212    /// from top to bottom.
213    pub fn copy(&self, i: usize) -> Option<T> {
214        if self.size() == 0 || i > self.size() - 1 {
215            None
216        } else {
217            Some(self.elements[self.size() - (i + 1)].clone())
218        }
219    }
220
221    /// Returns a copy of the n top-most elements
222    /// of the stack. The first element of the returned vector
223    /// is the nth element counted from the top of the stack.
224    pub fn copy_vec(&self, n: usize) -> Option<Vec<T>> {
225        if n > self.size() {
226            None
227        } else {
228            let mut cpy = Vec::with_capacity(n);
229            for i in 0..n {
230                cpy.push(self.elements[self.size() - n + i].clone());
231            }
232            Some(cpy)
233        }
234    }
235
236    /// Pushes the argument to the stack where the last
237    /// element of the argument will at the top of the stack.
238    pub fn push_vec(&mut self, to_push: Vec<T>) {
239        self.elements.extend(to_push);
240    }
241}
242
243#[cfg(test)]
244mod tests {
245    use super::*;
246
247    #[test]
248    fn pop_vec_in_right_order() {
249        let mut test_stack = PushStack {
250            elements: vec![1, 2, 3],
251        };
252
253        match test_stack.pop_vec(2) {
254            None => assert!(false),
255            Some(pv) => assert_eq!(pv[0], 2),
256        }
257    }
258
259    #[test]
260    fn pop_vec_max_index() {
261        let mut test_stack = PushStack {
262            elements: vec![1, 2, 3],
263        };
264        match test_stack.pop_vec(4) {
265            None => assert!(true),
266            Some(_pv) => assert!(false),
267        }
268    }
269
270    #[test]
271    fn push_vec_in_right_order() {
272        let mut test_stack = PushStack {
273            elements: vec![1, 2, 3],
274        };
275        let test_vec = vec![4, 5];
276        test_stack.push_vec(test_vec);
277        assert_eq!(test_stack.elements, [1, 2, 3, 4, 5]);
278    }
279
280    #[test]
281    fn copy_vec_preserves_stack() {
282        let test_stack = PushStack {
283            elements: vec![1, 2, 3],
284        };
285
286        match test_stack.copy_vec(2) {
287            None => assert!(false, "Should return values"),
288            Some(cv) => {
289                assert_eq!(cv.len(), 2);
290                assert_eq!(cv[0], 2);
291                assert_eq!(cv[1], 3);
292            }
293        }
294        assert_eq!(
295            test_stack.elements.len(),
296            3,
297            "Test stack should remain the same"
298        )
299    }
300
301    #[test]
302    fn equal_at_checks_equality_at_right_index() {
303        let test_stack = PushStack {
304            elements: vec![1, 2, 3, 4, 5],
305        };
306        assert_eq!(test_stack.equal_at(0, &5), Some(true));
307        assert_eq!(test_stack.equal_at(3, &2), Some(true));
308        assert_eq!(test_stack.equal_at(3, &1), Some(false));
309    }
310
311    #[test]
312    fn yank_vec_returns_right_order() {
313        let mut test_stack = PushStack {
314            elements: vec![1, 2, 3, 4, 5],
315        };
316        let mut test_idx = 1;
317        test_stack.yank(test_idx);
318        assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
319        test_idx = 5; // No change
320        test_stack.yank(test_idx);
321        assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
322        test_idx = 3;
323        test_stack.yank(test_idx);
324        assert_eq!(test_stack.elements, [1, 3, 5, 4, 2]);
325        test_idx = 0; // No change
326        test_stack.yank(test_idx);
327        assert_eq!(test_stack.elements, [1, 3, 5, 4, 2]);
328    }
329
330    #[test]
331    fn shove_vec_returns_right_order() {
332        let mut test_stack = PushStack {
333            elements: vec![1, 2, 3, 4, 5],
334        };
335        let mut test_idx = 1;
336        test_stack.shove(test_idx);
337        assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
338        test_idx = 4; // Push to bottom
339        test_stack.shove(test_idx);
340        assert_eq!(test_stack.elements, [4, 1, 2, 3, 5]);
341        test_idx = 3;
342        test_stack.shove(test_idx);
343        assert_eq!(test_stack.elements, [4, 5, 1, 2, 3]);
344        test_idx = 0; // No change
345        test_stack.shove(test_idx);
346        assert_eq!(test_stack.elements, [4, 5, 1, 2, 3]);
347    }
348
349    #[test]
350    fn last_eq_preserves_vector() {
351        let test_stack = PushStack {
352            elements: vec![1, 2, 3, 4, 5],
353        };
354        let candidate = 5;
355        assert_eq!(test_stack.last_eq(&candidate), true);
356        let candidate = 4;
357        assert_eq!(test_stack.last_eq(&candidate), false);
358        assert_eq!(test_stack.size(), 5);
359        let test_stack = PushStack {
360            elements: Vec::new(),
361        };
362        assert_eq!(test_stack.last_eq(&candidate), false);
363    }
364
365    #[test]
366    fn replace_returns_right_offset() {
367        let mut test_stack = PushStack {
368            elements: vec![1, 2, 3, 4, 5],
369        };
370        assert_eq!(test_stack.replace(1, 19), Ok(()));
371        assert_eq!(test_stack.replace(5, 19), Err(1));
372        assert_eq!(test_stack.replace(6, 19), Err(2));
373        assert_eq!(test_stack.replace(4, 19), Ok(()));
374        assert_eq!(test_stack.replace(0, 19), Ok(()));
375        assert_eq!(test_stack.to_string(), "19 19 3 2 19");
376    }
377
378    #[test]
379    fn reverse_elements() {
380        let mut test_stack = PushStack {
381            elements: vec![1, 2, 3, 4, 5],
382        };
383        test_stack.reverse();
384        assert_eq!(test_stack.elements, [5, 4, 3, 2, 1]);
385    }
386}