piccolo/
stack.rs

1use std::{
2    iter,
3    ops::{Bound, Index, IndexMut, RangeBounds},
4    slice::{self, SliceIndex},
5};
6
7use allocator_api2::vec;
8use gc_arena::allocator_api::MetricsAlloc;
9
10use crate::{Context, FromMultiValue, FromValue, IntoMultiValue, IntoValue, TypeError, Value};
11
12pub struct Stack<'gc, 'a> {
13    values: &'a mut vec::Vec<Value<'gc>, MetricsAlloc<'gc>>,
14    bottom: usize,
15}
16
17impl<'gc, 'a> Stack<'gc, 'a> {
18    pub fn new(values: &'a mut vec::Vec<Value<'gc>, MetricsAlloc<'gc>>, bottom: usize) -> Self {
19        assert!(values.len() >= bottom);
20        Self { values, bottom }
21    }
22
23    pub fn sub_stack(&mut self, bottom: usize) -> Stack<'gc, '_> {
24        Stack {
25            values: self.values,
26            bottom: self.bottom + bottom,
27        }
28    }
29
30    pub fn get(&self, i: usize) -> Value<'gc> {
31        self.values
32            .get(self.bottom + i)
33            .copied()
34            .unwrap_or_default()
35    }
36
37    pub fn push_back(&mut self, value: Value<'gc>) {
38        self.values.push(value);
39    }
40
41    pub fn push_front(&mut self, value: Value<'gc>) {
42        self.values.insert(self.bottom, value);
43    }
44
45    pub fn pop_back(&mut self) -> Value<'gc> {
46        if self.values.len() > self.bottom {
47            self.values.pop().unwrap()
48        } else {
49            Value::Nil
50        }
51    }
52
53    pub fn pop_front(&mut self) -> Value<'gc> {
54        if self.values.len() > self.bottom {
55            self.values.remove(self.bottom)
56        } else {
57            Value::Nil
58        }
59    }
60
61    pub fn len(&self) -> usize {
62        self.values.len() - self.bottom
63    }
64
65    pub fn is_empty(&self) -> bool {
66        self.values.len() == self.bottom
67    }
68
69    pub fn clear(&mut self) {
70        self.values.truncate(self.bottom);
71    }
72
73    pub fn resize(&mut self, size: usize) {
74        self.values.resize(self.bottom + size, Value::Nil);
75    }
76
77    pub fn drain<R: RangeBounds<usize>>(
78        &mut self,
79        range: R,
80    ) -> vec::Drain<Value<'gc>, MetricsAlloc<'gc>> {
81        let start = match range.start_bound().cloned() {
82            Bound::Included(r) => Bound::Included(self.bottom + r),
83            Bound::Excluded(r) => Bound::Excluded(self.bottom + r),
84            Bound::Unbounded => Bound::Included(self.bottom),
85        };
86        let end = match range.end_bound().cloned() {
87            Bound::Included(r) => Bound::Included(self.bottom + r),
88            Bound::Excluded(r) => Bound::Excluded(self.bottom + r),
89            Bound::Unbounded => Bound::Unbounded,
90        };
91        self.values.drain((start, end))
92    }
93
94    pub fn into_back(&mut self, ctx: Context<'gc>, v: impl IntoMultiValue<'gc>) {
95        for v in v.into_multi_value(ctx) {
96            self.values.push(v.into_value(ctx));
97        }
98    }
99
100    pub fn into_front(&mut self, ctx: Context<'gc>, v: impl IntoMultiValue<'gc>) {
101        let mut c = 0;
102        for v in v.into_multi_value(ctx) {
103            c += 1;
104            self.values.push(v.into_value(ctx));
105        }
106        self.values[self.bottom..].rotate_right(c);
107    }
108
109    pub fn from_back<V: FromValue<'gc>>(&mut self, ctx: Context<'gc>) -> Result<V, TypeError> {
110        V::from_value(ctx, self.pop_back())
111    }
112
113    pub fn from_front<V: FromValue<'gc>>(&mut self, ctx: Context<'gc>) -> Result<V, TypeError> {
114        V::from_value(ctx, self.pop_front())
115    }
116
117    pub fn replace(&mut self, ctx: Context<'gc>, v: impl IntoMultiValue<'gc>) {
118        self.clear();
119        self.extend(v.into_multi_value(ctx));
120    }
121
122    pub fn consume<V: FromMultiValue<'gc>>(&mut self, ctx: Context<'gc>) -> Result<V, TypeError> {
123        V::from_multi_value(ctx, self.drain(..))
124    }
125}
126
127impl<'gc: 'b, 'a, 'b> IntoIterator for &'b Stack<'gc, 'a> {
128    type Item = Value<'gc>;
129    type IntoIter = iter::Copied<slice::Iter<'b, Value<'gc>>>;
130
131    fn into_iter(self) -> Self::IntoIter {
132        self.values[self.bottom..].iter().copied()
133    }
134}
135
136impl<'gc, 'a> Extend<Value<'gc>> for Stack<'gc, 'a> {
137    fn extend<T: IntoIterator<Item = Value<'gc>>>(&mut self, iter: T) {
138        self.values.extend(iter);
139    }
140}
141
142impl<'gc, 'a, 'b> Extend<Value<'gc>> for &'b mut Stack<'gc, 'a> {
143    fn extend<T: IntoIterator<Item = Value<'gc>>>(&mut self, iter: T) {
144        self.values.extend(iter);
145    }
146}
147
148impl<'gc: 'b, 'a, 'b> Extend<&'a Value<'gc>> for Stack<'gc, 'a> {
149    fn extend<T: IntoIterator<Item = &'a Value<'gc>>>(&mut self, iter: T) {
150        self.values.extend(iter);
151    }
152}
153
154impl<'gc: 'b, 'a, 'b, 'c> Extend<&'b Value<'gc>> for &'c mut Stack<'gc, 'a> {
155    fn extend<T: IntoIterator<Item = &'b Value<'gc>>>(&mut self, iter: T) {
156        self.values.extend(iter);
157    }
158}
159
160impl<'gc, 'a, I: SliceIndex<[Value<'gc>]>> Index<I> for Stack<'gc, 'a> {
161    type Output = <Vec<Value<'gc>> as Index<I>>::Output;
162
163    fn index(&self, index: I) -> &Self::Output {
164        &self.values[self.bottom..][index]
165    }
166}
167
168impl<'gc, 'a, I: SliceIndex<[Value<'gc>]>> IndexMut<I> for Stack<'gc, 'a> {
169    fn index_mut(&mut self, index: I) -> &mut Self::Output {
170        &mut self.values[self.bottom..][index]
171    }
172}