rpds/list/
mod.rs

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