summaryrefslogtreecommitdiffstats
path: root/melib/src/structs.rs
blob: 3111bfc62b415a277591aba85d71e0e73eaef930 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::iter::Extend;
use std::ops::Index;

#[derive(Debug, Default)]
pub struct StackVec<T: Default + Copy + std::fmt::Debug> {
    len: usize,
    array: [T; 32],
    heap_vec: Vec<T>,
}

impl<T: Default + Copy + std::fmt::Debug> StackVec<T> {
    pub fn new() -> Self {
        StackVec {
            len: 0,
            array: [T::default(); 32],
            heap_vec: Vec::new(),
        }
    }
    pub fn push(&mut self, ind: T) {
        if self.len == self.array.len() {
            if self.heap_vec.is_empty() {
                self.heap_vec.reserve(32);
                for _ in 0..8 {
                    self.heap_vec.push(T::default());
                }
            }
            self.heap_vec[0..8].copy_from_slice(&self.array);
            self.heap_vec.push(ind);
        } else if self.len > self.array.len() {
            self.heap_vec.push(ind);
        } else {
            self.array[self.len] = ind;
        }
        self.len += 1;
    }
    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            return None;
        }
        if self.len >= self.array.len() {
            self.len -= 1;
            self.heap_vec.pop()
        } else {
            let ret = self.array[self.len - 1];
            self.len -= 1;
            Some(ret)
        }
    }
    pub fn len(&self) -> usize {
        self.len
    }
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }
    pub fn iter(&self) -> StackVecIter<T> {
        StackVecIter {
            stack: &self,
            range: 0..self.len,
        }
    }
}

pub struct StackVecIter<'a, T: Default + Copy + std::fmt::Debug> {
    stack: &'a StackVec<T>,
    range: std::ops::Range<usize>,
}

impl<'a, T: Default + Copy + std::fmt::Debug> Iterator for StackVecIter<'a, T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<&'a T> {
        if self.range.len() == 0 {
            None
        } else {
            let idx = self.range.start;
            self.range.start += 1;
            Some(&self.stack[idx])
        }
    }
}
impl<'a, T: Default + Copy + std::fmt::Debug> std::iter::DoubleEndedIterator
    for StackVecIter<'a, T>
{
    fn next_back(&mut self) -> Option<&'a T> {
        if self.range.len() == 0 {
            None
        } else {
            let idx = self.range.end - 1;
            self.range.end -= 1;
            Some(&self.stack[idx])
        }
    }
}

impl<T: Default + Copy + std::fmt::Debug> Index<usize> for StackVec<T> {
    type Output = T;

    fn index(&self, idx: usize) -> &T {
        if self.len >= self.array.len() {
            &self.heap_vec[idx]
        } else {
            &self.array[idx]
        }
    }
}

impl<T: Default + Copy + std::fmt::Debug> Extend<T> for StackVec<T> {
    fn extend<I>(&mut self, iter: I)
    where
        I: IntoIterator<Item = T>,
    {
        for elem in iter {
            self.push(elem);
        }
    }
}