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}