rpds/list/
mod.rs

1use alloc::vec::Vec;
2use archery::*;
3use core::borrow::Borrow;
4use core::cmp::Ordering;
5use core::fmt::Display;
6use core::hash::{Hash, Hasher};
7use core::iter::FromIterator;
8
9// TODO Use impl trait instead of this when available.
10pub type Iter<'a, T, P> = core::iter::Map<IterPtr<'a, T, P>, fn(&SharedPointer<T, P>) -> &T>;
11
12#[doc(hidden)]
13#[macro_export]
14macro_rules! list_reverse {
15    ($ptr_kind:ty ; ; $($reversed:expr),*) => {
16         {
17            #[allow(unused_mut)]
18            let mut l: List<_, $ptr_kind> = $crate::List::new_with_ptr_kind();
19            $(
20                l.push_front_mut($reversed);
21            )*
22            l
23         }
24    };
25    ($ptr_kind:ty ; $h:expr ; $($reversed:expr),*) => {
26        $crate::list_reverse!($ptr_kind ; ; $h, $($reversed),*)
27    };
28    ($ptr_kind:ty ; $h:expr, $($t:expr),+ ; $($reversed:expr),*) => {
29        $crate::list_reverse!($ptr_kind ; $($t),* ; $h, $($reversed),*)
30    };
31
32    // This is just to handle the cases where this macro is called with an extra comma in the
33    // reserve list, which can happen in a recursive call.
34    ($ptr_kind:ty ; $($t:expr),* ; $($reversed:expr),*,) => {
35        $crate::list_reverse!($ptr_kind ; $($t),* ; $($reversed),*)
36    };
37}
38
39/// Creates a [`List`](crate::List) containing the given arguments:
40///
41/// ```
42/// # use rpds::*;
43/// #
44/// let l = List::new()
45///     .push_front(3)
46///     .push_front(2)
47///     .push_front(1);
48///
49/// assert_eq!(list![1, 2, 3], l);
50/// ```
51#[macro_export]
52macro_rules! list {
53    ($($e:expr),*) => {
54        $crate::list_reverse!(::archery::RcK ; $($e),* ; )
55    };
56}
57
58/// Creates a [`List`](crate::List) that implements `Sync`, containing the given arguments:
59///
60/// ```
61/// # use rpds::*;
62/// #
63/// let l = List::new_sync()
64///     .push_front(3)
65///     .push_front(2)
66///     .push_front(1);
67///
68/// assert_eq!(list_sync![1, 2, 3], l);
69///
70/// fn is_sync() -> impl Sync {
71///     list_sync![0, 1, 1, 2, 3, 5, 8]
72/// }
73/// ```
74#[macro_export]
75macro_rules! list_sync {
76    ($($e:expr),*) => {
77        $crate::list_reverse!(::archery::ArcTK ; $($e),* ; )
78    };
79}
80
81/// A persistent list with structural sharing.
82///
83/// # Complexity
84///
85/// Let *n* be the number of elements in the list.
86///
87/// ## Temporal complexity
88///
89/// | Operation         | Average | Worst case  |
90/// |:----------------- | -------:| -----------:|
91/// | `new()`           |    Θ(1) |        Θ(1) |
92/// | `push_front()`    |    Θ(1) |        Θ(1) |
93/// | `drop_first()`    |    Θ(1) |        Θ(1) |
94/// | `reverse()`       |    Θ(n) |        Θ(n) |
95/// | `first()`         |    Θ(1) |        Θ(1) |
96/// | `last()`          |    Θ(1) |        Θ(1) |
97/// | `len()`           |    Θ(1) |        Θ(1) |
98/// | `clone()`         |    Θ(1) |        Θ(1) |
99/// | iterator creation |    Θ(1) |        Θ(1) |
100/// | iterator step     |    Θ(1) |        Θ(1) |
101/// | iterator full     |    Θ(n) |        Θ(n) |
102///
103/// # Implementation details
104///
105/// This is your classic functional list with "cons" and "nil" nodes, with a little extra sauce to
106/// make some operations more efficient.
107#[derive(Debug)]
108pub struct List<T, P = RcK>
109where
110    P: SharedPointerKind,
111{
112    head: Option<SharedPointer<Node<T, P>, P>>,
113    last: Option<SharedPointer<T, P>>,
114    length: usize,
115}
116
117#[derive(Debug)]
118struct Node<T, P>
119where
120    P: SharedPointerKind,
121{
122    value: SharedPointer<T, P>,
123    next: Option<SharedPointer<Node<T, P>, P>>,
124}
125
126impl<T, P> Clone for Node<T, P>
127where
128    P: SharedPointerKind,
129{
130    fn clone(&self) -> Node<T, P> {
131        Node { value: SharedPointer::clone(&self.value), next: self.next.clone() }
132    }
133}
134
135pub type ListSync<T> = List<T, ArcTK>;
136
137impl<T> ListSync<T> {
138    #[must_use]
139    pub fn new_sync() -> ListSync<T> {
140        List::new_with_ptr_kind()
141    }
142}
143
144impl<T> List<T> {
145    #[must_use]
146    pub fn new() -> List<T> {
147        List::new_with_ptr_kind()
148    }
149}
150
151impl<T, P> List<T, P>
152where
153    P: SharedPointerKind,
154{
155    #[must_use]
156    pub fn new_with_ptr_kind() -> List<T, P> {
157        List { head: None, last: None, length: 0 }
158    }
159
160    #[must_use]
161    pub fn first(&self) -> Option<&T> {
162        self.head.as_ref().map(|node| node.value.borrow())
163    }
164
165    #[must_use]
166    pub fn last(&self) -> Option<&T> {
167        self.last.as_ref().map(Borrow::borrow)
168    }
169
170    #[must_use]
171    pub fn drop_first(&self) -> Option<List<T, P>> {
172        let mut new_list = self.clone();
173
174        if new_list.drop_first_mut() { Some(new_list) } else { None }
175    }
176
177    pub fn drop_first_mut(&mut self) -> bool {
178        self.head.take().is_some_and(|h| {
179            self.head.clone_from(&h.next);
180            self.length -= 1;
181
182            if self.length == 0 {
183                self.last = None;
184            }
185
186            true
187        })
188    }
189
190    fn push_front_ptr_mut(&mut self, v: SharedPointer<T, P>) {
191        if self.length == 0 {
192            self.last = Some(SharedPointer::clone(&v));
193        }
194
195        let new_head = Node { value: v, next: self.head.take() };
196
197        self.head = Some(SharedPointer::new(new_head));
198        self.length += 1;
199    }
200
201    #[must_use]
202    pub fn push_front(&self, v: T) -> List<T, P> {
203        let mut new_list = self.clone();
204
205        new_list.push_front_mut(v);
206
207        new_list
208    }
209
210    pub fn push_front_mut(&mut self, v: T) {
211        self.push_front_ptr_mut(SharedPointer::new(v));
212    }
213
214    #[must_use]
215    pub fn reverse(&self) -> List<T, P> {
216        let mut new_list = List::new_with_ptr_kind();
217
218        // It is significantly faster to re-implement this here than to clone and call
219        // `reverse_mut()`.  The reason is that since this is a linear data structure all nodes will
220        // need to be cloned given that the ref count would be greater than one.
221
222        for v in self.iter_ptr() {
223            new_list.push_front_ptr_mut(SharedPointer::clone(v));
224        }
225
226        new_list
227    }
228
229    pub fn reverse_mut(&mut self) {
230        self.last = self.head.as_ref().map(|next| SharedPointer::clone(&next.value));
231
232        let mut prev: Option<SharedPointer<Node<T, P>, P>> = None;
233        let mut current: Option<SharedPointer<Node<T, P>, P>> = self.head.take();
234
235        while let Some(mut curr_ptr) = current {
236            let curr = SharedPointer::make_mut(&mut curr_ptr);
237            let curr_next = curr.next.take();
238
239            curr.next = prev.take();
240
241            current = curr_next;
242            prev = Some(curr_ptr);
243        }
244
245        self.head = prev;
246    }
247
248    #[must_use]
249    #[inline]
250    pub fn len(&self) -> usize {
251        self.length
252    }
253
254    #[must_use]
255    #[inline]
256    pub fn is_empty(&self) -> bool {
257        self.len() == 0
258    }
259
260    pub fn iter(&self) -> Iter<'_, T, P> {
261        self.iter_ptr().map(|v| v.borrow())
262    }
263
264    #[must_use]
265    pub(crate) fn iter_ptr(&self) -> IterPtr<'_, T, P> {
266        IterPtr::new(self)
267    }
268}
269
270impl<T, P> List<T, P>
271where
272    T: Clone,
273    P: SharedPointerKind,
274{
275    #[must_use]
276    pub(crate) fn first_mut(&mut self) -> Option<&mut T> {
277        self.head
278            .as_mut()
279            .map(|node| SharedPointer::make_mut(&mut SharedPointer::make_mut(node).value))
280    }
281}
282
283impl<T, P> Default for List<T, P>
284where
285    P: SharedPointerKind,
286{
287    fn default() -> List<T, P> {
288        List::new_with_ptr_kind()
289    }
290}
291
292impl<T: PartialEq, P, PO> PartialEq<List<T, PO>> for List<T, P>
293where
294    P: SharedPointerKind,
295    PO: SharedPointerKind,
296{
297    fn eq(&self, other: &List<T, PO>) -> bool {
298        self.length == other.length && self.iter().eq(other.iter())
299    }
300}
301
302impl<T: Eq, P> Eq for List<T, P> where P: SharedPointerKind {}
303
304impl<T: PartialOrd<T>, P, PO> PartialOrd<List<T, PO>> for List<T, P>
305where
306    P: SharedPointerKind,
307    PO: SharedPointerKind,
308{
309    fn partial_cmp(&self, other: &List<T, PO>) -> Option<Ordering> {
310        self.iter().partial_cmp(other.iter())
311    }
312}
313
314impl<T: Ord, P> Ord for List<T, P>
315where
316    P: SharedPointerKind,
317{
318    fn cmp(&self, other: &List<T, P>) -> Ordering {
319        self.iter().cmp(other.iter())
320    }
321}
322
323impl<T: Hash, P> Hash for List<T, P>
324where
325    P: SharedPointerKind,
326{
327    fn hash<H: Hasher>(&self, state: &mut H) {
328        // Add the hash of length so that if two collections are added one after the other it doesn't
329        // hash to the same thing as a single collection with the same elements in the same order.
330        self.len().hash(state);
331
332        for e in self {
333            e.hash(state);
334        }
335    }
336}
337
338impl<T, P> Clone for List<T, P>
339where
340    P: SharedPointerKind,
341{
342    fn clone(&self) -> List<T, P> {
343        List { head: self.head.clone(), last: self.last.clone(), length: self.length }
344    }
345}
346
347impl<T: Display, P> Display for List<T, P>
348where
349    P: SharedPointerKind,
350{
351    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
352        let mut first = true;
353
354        fmt.write_str("[")?;
355
356        for v in self {
357            if !first {
358                fmt.write_str(", ")?;
359            }
360            v.fmt(fmt)?;
361            first = false;
362        }
363
364        fmt.write_str("]")
365    }
366}
367
368impl<'a, T, P> IntoIterator for &'a List<T, P>
369where
370    P: SharedPointerKind,
371{
372    type Item = &'a T;
373    type IntoIter = Iter<'a, T, P>;
374
375    fn into_iter(self) -> Iter<'a, T, P> {
376        self.iter()
377    }
378}
379
380impl<T, P> FromIterator<T> for List<T, P>
381where
382    P: SharedPointerKind,
383{
384    fn from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> List<T, P> {
385        let iter = into_iter.into_iter();
386        let (min_size, max_size_hint) = iter.size_hint();
387        let mut vec: Vec<T> = Vec::with_capacity(max_size_hint.unwrap_or(min_size));
388
389        for e in iter {
390            vec.push(e);
391        }
392
393        let mut list: List<T, P> = List::new_with_ptr_kind();
394
395        for e in vec.into_iter().rev() {
396            list.push_front_mut(e);
397        }
398
399        list
400    }
401}
402
403// Drop the list iteratively to prevent stack overflow.
404impl<T, P> Drop for List<T, P>
405where
406    P: SharedPointerKind,
407{
408    fn drop(&mut self) {
409        let mut head = self.head.take();
410        while let Some(node) = head {
411            match SharedPointer::try_unwrap(node) {
412                Ok(mut node) => {
413                    head = node.next.take();
414                }
415                _ => {
416                    break;
417                }
418            }
419        }
420    }
421}
422
423#[derive(Debug)]
424pub struct IterPtr<'a, T, P>
425where
426    P: SharedPointerKind,
427{
428    next: Option<&'a Node<T, P>>,
429    length: usize,
430}
431
432impl<T, P> IterPtr<'_, T, P>
433where
434    P: SharedPointerKind,
435{
436    fn new(list: &List<T, P>) -> IterPtr<'_, T, P> {
437        IterPtr { next: list.head.as_ref().map(AsRef::as_ref), length: list.len() }
438    }
439}
440
441impl<'a, T, P> Iterator for IterPtr<'a, T, P>
442where
443    P: SharedPointerKind,
444{
445    type Item = &'a SharedPointer<T, P>;
446
447    fn next(&mut self) -> Option<&'a SharedPointer<T, P>> {
448        match self.next {
449            Some(Node { value: v, next: t }) => {
450                self.next = t.as_ref().map(AsRef::as_ref);
451                self.length -= 1;
452                Some(v)
453            }
454            None => None,
455        }
456    }
457
458    fn size_hint(&self) -> (usize, Option<usize>) {
459        (self.length, Some(self.length))
460    }
461}
462
463impl<T, P> ExactSizeIterator for IterPtr<'_, T, P> where P: SharedPointerKind {}
464
465#[cfg(feature = "serde")]
466pub mod serde {
467    use super::*;
468    use ::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
469    use ::serde::ser::{Serialize, Serializer};
470    use core::fmt;
471    use core::marker::PhantomData;
472
473    impl<T, P> Serialize for List<T, P>
474    where
475        T: Serialize,
476        P: SharedPointerKind,
477    {
478        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
479            serializer.collect_seq(self)
480        }
481    }
482
483    impl<'de, T, P> Deserialize<'de> for List<T, P>
484    where
485        T: Deserialize<'de>,
486        P: SharedPointerKind,
487    {
488        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<List<T, P>, D::Error> {
489            deserializer
490                .deserialize_seq(ListVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData })
491        }
492    }
493
494    struct ListVisitor<T, P> {
495        _phantom_t: PhantomData<T>,
496        _phantom_p: PhantomData<P>,
497    }
498
499    impl<'de, T, P> Visitor<'de> for ListVisitor<T, P>
500    where
501        T: Deserialize<'de>,
502        P: SharedPointerKind,
503    {
504        type Value = List<T, P>;
505
506        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
507            formatter.write_str("a sequence")
508        }
509
510        fn visit_seq<A>(self, mut seq: A) -> Result<List<T, P>, A::Error>
511        where
512            A: SeqAccess<'de>,
513        {
514            let mut vec: Vec<T> = if let Some(capacity) = seq.size_hint() {
515                Vec::with_capacity(capacity)
516            } else {
517                Vec::new()
518            };
519
520            while let Some(value) = seq.next_element()? {
521                vec.push(value);
522            }
523
524            let mut list: List<T, P> = List::new_with_ptr_kind();
525
526            for value in vec.into_iter().rev() {
527                list.push_front_mut(value);
528            }
529
530            Ok(list)
531        }
532    }
533}
534
535#[cfg(test)]
536mod test;