stack_list/lib.rs
1//! This library implements a heapless linked list by keeping each element on the stack.
2//!
3//! The primary purpose is to efficiently keep a context when traversing trees recursively.
4//!
5//! Compared to a traditional linked list, this has a few drawbacks:
6//! * Not "self-contained": you cannot easily store a `Node` as a member like you would a
7//! `LinkedList`.
8//! * Many methods use recursion and lead to increase stack memory usage (because of function
9//! frames).
10//!
11//! The main advantage is that it does not need any heap allocation, and can grow to arbitrary
12//! sizes (only limited by your stack size).
13#![no_std]
14
15/// A stack-based linked list.
16///
17/// This is a node in a traditional linked list. The main difference is that it does not box the
18/// next element, but simply points to it. As a result, it is harder to pass around or to mutate,
19/// but has the advantage of not requiring any heap allocation.
20#[derive(Debug, Clone, Copy, Eq, PartialEq)]
21pub enum Node<'a, T> {
22 /// An empty list.
23 Root,
24 /// A node in the list with some data and a tail.
25 Head {
26 /// Some data attached on this node. This is the first element of this list.
27 data: T,
28 /// The rest of the list as a tail node.
29 tail: &'a Node<'a, T>,
30 },
31}
32
33/// Convenient macro to define a stack list from a slice literal.
34///
35/// Note that this will actually define a bunch of local stack variables (one per item in the
36/// list). This is _not_ an expression to define a standalone stack list, this would be impossible.
37///
38/// # Examples
39///
40/// ```rust
41/// stack_list::make!(let my_list = [1, 2, 3, 4]);
42/// assert_eq!(my_list.len(), 4);
43/// assert_eq!(my_list.get(3), Some(&4));
44///
45/// println!("{:?}", my_list);
46/// ```
47#[macro_export]
48macro_rules! make {
49 ( let $name:ident = [ $head:expr $(,)? ] ) => {
50 let root = $crate::Node::Root;
51 let $name = root.prepend($head);
52 };
53 ( let $name:ident = [ $head:expr , $($tail:expr),* ] ) => {
54 $crate::make!(let n = [ $($tail),* ] );
55 let $name = n.prepend($head);
56 };
57}
58
59impl<'a, T> Node<'a, T> {
60 /// Create a new empty list.
61 pub fn new() -> Self {
62 Node::Root
63 }
64
65 /// Create a new list by prepending `self` with `data`.
66 pub fn prepend(&'a self, data: T) -> Self {
67 Node::Head { data, tail: self }
68 }
69
70 /// Returns an iterator on this list.
71 pub fn iter(&'a self) -> impl Iterator<Item = &'a T> {
72 self
73 }
74
75 /// Run the given closure on each item from this list, starting from the end.
76 pub fn for_each_rev<F>(&self, mut f: F)
77 where
78 F: FnMut(&T),
79 {
80 self.for_each_rev_inner(&mut f);
81 }
82
83 /// Same as `for_each_rev`, but takes a `&mut F` so it can more easily recurse.
84 fn for_each_rev_inner<F>(&self, f: &mut F)
85 where
86 F: FnMut(&T),
87 {
88 if let &Node::Head { ref data, ref tail } = self {
89 tail.for_each_rev_inner(f);
90 f(data);
91 }
92 }
93
94 /// Returns the next element in the list, if any.
95 pub fn tail(&self) -> Option<&Self> {
96 match self {
97 Node::Root => None,
98 Node::Head { tail, .. } => Some(tail),
99 }
100 }
101
102 /// Returns the first data element in this list, if any.
103 pub fn first(&self) -> Option<&T> {
104 match self {
105 Node::Root => None,
106 Node::Head { data, .. } => Some(&data),
107 }
108 }
109
110 /// Returns the length of this list.
111 pub fn len(&self) -> usize {
112 self.tail().map_or(0, |t| 1 + t.len())
113 }
114
115 /// Returns `true` if this list is empty.
116 pub fn is_empty(&self) -> bool {
117 match self {
118 Node::Root => true,
119 _ => false,
120 }
121 }
122
123 /// Returns a sublist made by skipping the `n` first elements.
124 ///
125 /// Returns `None` if `n >= self.len()`.
126 pub fn skip(&self, n: usize) -> Option<&Self> {
127 match n {
128 0 => Some(self),
129 n => self.tail().and_then(|t| t.skip(n - 1)),
130 }
131 }
132
133 /// Returns the data at index `n`.
134 ///
135 /// Returns `None` if `n >= self.len()`.
136 pub fn get(&self, n: usize) -> Option<&T> {
137 self.skip(n).and_then(Node::first)
138 }
139
140 /// Returns the data for the last item in this list.
141 ///
142 /// Returns `None` if `self` is empty.
143 pub fn last(&self) -> Option<&T> {
144 match self {
145 Node::Root => None,
146 Node::Head { data, tail } => Some(tail.last().unwrap_or(data)),
147 }
148 }
149
150 /// Fold the given function over this list.
151 ///
152 /// Conceptually, runs the code:
153 ///
154 /// ```rust,ignore
155 /// for data in self {
156 /// start = f(start, data);
157 /// }
158 /// start
159 /// ```
160 pub fn fold<F, S>(&self, start: S, mut f: F) -> S
161 where
162 F: FnMut(S, T) -> S,
163 T: Clone,
164 {
165 match self {
166 Node::Root => start,
167 Node::Head { tail, data } => tail.fold(f(start, data.clone()), f),
168 }
169 }
170
171 /// Reverse this list.
172 ///
173 /// This does not return a stacklist; instead, it runs `f` on a reversed version of `self`.
174 pub fn reverse<F, R>(&self, f: F) -> R
175 where
176 F: for<'b> FnOnce(&'b Node<'b, T>) -> R,
177 R: 'static,
178 T: Clone,
179 {
180 fn reverse_inner<'b, T, F, R>(target: &Node<'b, T>, source: &Node<'b, T>, f: F) -> R
181 where
182 F: for<'c> FnOnce(&'c Node<'c, T>) -> R,
183 R: 'static,
184 T: Clone,
185 {
186 match source {
187 Node::Root => f(target),
188 Node::Head { data, tail } => reverse_inner(&target.prepend(data.clone()), tail, f),
189 }
190 }
191
192 reverse_inner(&Node::Root, self, f)
193 }
194
195 /// Prepend all the elements from the given iterator, in reverse order.
196 ///
197 /// # Examples
198 ///
199 /// ```rust
200 /// stack_list::make!(let a = [3, 4, 5]);
201 /// assert_eq!(a.get(0), Some(&3));
202 ///
203 /// a.prepend_all_rev([2, 1].iter().copied(), |b| {
204 /// assert_eq!(b.get(0), Some(&1));
205 /// });
206 /// ```
207 pub fn prepend_all_rev<I, F, R>(&self, mut i: I, f: F) -> R
208 where
209 I: Iterator<Item = T>,
210 F: for<'b> FnOnce(&'b Node<'b, T>) -> R,
211 R: 'static,
212 {
213 match i.next() {
214 None => f(self),
215 Some(x) => self.prepend(x).prepend_all_rev(i, f),
216 }
217 }
218
219 /// Prepend all the elements from the given iterator.
220 ///
221 /// # Examples
222 ///
223 /// ```rust
224 /// stack_list::make!(let a = [3, 4, 5]);
225 /// assert_eq!(a.get(0), Some(&3));
226 ///
227 /// a.prepend_all([1, 2].iter().copied(), |b| {
228 /// assert_eq!(b.get(0), Some(&1));
229 /// });
230 /// ```
231 pub fn prepend_all<I, F, R>(&self, i: I, f: F) -> R
232 where
233 I: DoubleEndedIterator<Item = T>,
234 F: for<'b> FnOnce(&'b Node<'b, T>) -> R,
235 R: 'static,
236 {
237 self.prepend_all_rev(i.rev(), f)
238 }
239
240 /// Build a stacklist using the items from the iterator in reverse order.
241 ///
242 /// Note: this does not return the stacklist. Instead, it calls the given closure
243 /// with the generated list.
244 pub fn from_rev_iterator<I, F, R>(i: I, f: F) -> R
245 where
246 I: Iterator<Item = T>,
247 F: for<'b> FnOnce(&'b Node<'b, T>) -> R,
248 R: 'static,
249 {
250 Node::prepend_all_rev(&Node::Root, i, f)
251 }
252
253 /// Build a stacklist using the items from the iterator.
254 ///
255 /// Note: this does not return the stacklist. Instead, it calls the given closure
256 /// with the generated list.
257 pub fn from_iterator<I, F, R>(i: I, f: F) -> R
258 where
259 I: DoubleEndedIterator<Item = T>,
260 F: for<'b> FnOnce(&'b Node<'b, T>) -> R,
261 R: 'static,
262 {
263 Node::from_rev_iterator(i.rev(), f)
264 }
265}
266
267impl<'b, T> Iterator for &'b Node<'b, T> {
268 type Item = &'b T;
269
270 fn next(&mut self) -> Option<Self::Item> {
271 match self {
272 Node::Root => None,
273 Node::Head { data, tail } => {
274 *self = tail;
275 Some(&data)
276 }
277 }
278 }
279}