Skip to main content

standard_lib/collections/cons/tree/
branch.rs

1use std::{fmt::{self, Debug}, mem, ops::Deref, rc::Rc};
2
3use super::{Iter, OwnedIter, RcIter, UniqueIter};
4
5/// A references counted, linked list implemented similar to a cons list. This type is useful as an
6/// list of immutable items with cheap, shallow cloning, that can share nodes with other instances.
7///
8/// When cloned, only the 'head' of the tree is cloned (just an `Rc`), with all of the elements
9/// included in both list. As a result, the data structure is only mutable from the head, where
10/// elements can be [`push`](Self::push)ed or [`pop`](Self::pop_to_owned)ped. This cheap cloning is
11/// helpful for implementing procedures such that include rollbacks or branching.
12#[derive(#[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for ConsBranch<T> {
    #[inline]
    fn eq(&self, other: &ConsBranch<T>) -> bool { self.inner == other.inner }
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for ConsBranch<T> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Option<Rc<ConsNode<T>>>>;
    }
}Eq, #[automatically_derived]
impl<T: ::core::hash::Hash> ::core::hash::Hash for ConsBranch<T> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.inner, state)
    }
}Hash)]
13pub struct ConsBranch<T> {
14    pub(crate) inner: Option<Rc<ConsNode<T>>>,
15}
16
17/// Largely intended as an internal type, these nodes are returned by [`ConsBranch::into_iter_rc`]
18/// because the interior of the [`Rc`] can't be unwrapped in place.
19///
20/// To help using these nodes, a couple of useful traits have been implemented:
21/// - [`Deref<Target = T> for ConsNode<T>`](Deref) for accessing the contained value.
22/// - [`Into<ConsBranch> for Rc<ConsNode<T>>`](Into) for creating a new [`ConsBranch`] from an
23/// [`Rc`].
24///
25/// Note that cloning a `ConsNode` directly is _not_ cheap as it is with [`ConsBranch`] because
26/// the node contains the value (of type `T`) itself.
27#[derive(#[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for ConsNode<T> {
    #[inline]
    fn clone(&self) -> ConsNode<T> {
        ConsNode {
            value: ::core::clone::Clone::clone(&self.value),
            next: ::core::clone::Clone::clone(&self.next),
        }
    }
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for ConsNode<T> {
    #[inline]
    fn eq(&self, other: &ConsNode<T>) -> bool {
        self.value == other.value && self.next == other.next
    }
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for ConsNode<T> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<T>;
        let _: ::core::cmp::AssertParamIsEq<ConsBranch<T>>;
    }
}Eq, #[automatically_derived]
impl<T: ::core::hash::Hash> ::core::hash::Hash for ConsNode<T> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.value, state);
        ::core::hash::Hash::hash(&self.next, state)
    }
}Hash)]
28pub struct ConsNode<T> {
29    pub(crate) value: T,
30    pub(crate) next: ConsBranch<T>,
31}
32
33impl<T> ConsBranch<T> {
34    /// Creates a new, empty `ConsBranch`.
35    pub const fn new() -> ConsBranch<T> {
36        ConsBranch {
37            inner: None
38        }
39    }
40
41    /// Pushes a new element onto the start of this `ConsBranch`, updating this list's head without
42    /// affecting any overlapping lists (shallow clones).
43    pub fn push(&mut self, value: T) {
44        let old = mem::take(&mut self.inner);
45
46        self.inner = Some(Rc::new(ConsNode {
47            value,
48            next: ConsBranch {
49                inner: old
50            },
51        }))
52    }
53
54    /// Returns a reference to the element contained within the head node.
55    pub fn get_head(&self) -> Option<&T> {
56        self.inner.as_deref().map(ConsNode::deref)
57    }
58
59    /// Returns `true` if this `ConsBranch` contains no elements.
60    pub const fn is_empty(&self) -> bool {
61        self.inner.is_none()
62    }
63
64    /// Produces a borrowed [`Iterator<Item = &T>`](Iter) over all elements in this list, both
65    /// unique and shared.
66    pub fn iter(&self) -> Iter<'_, T> {
67        Iter {
68            inner: self.inner.as_deref(),
69        }
70    }
71
72    /// Produces an [`Iterator<Item = Rc<ConsNode<T>>>`](RcIter) over all of the underlying [`Rc`]
73    /// instances in this list.
74    ///
75    /// Each referenced element is considered 'shared' for the lifetime of the [`Rc`] produced by
76    /// this iterator. To return a `ConsBranch` to being unique, this iterator and all produced
77    /// [`Rc`]s need to be dropped.
78    pub fn into_iter_rc(&self) -> RcIter<T> {
79        RcIter {
80            // We clone here because we are also cloning every step, there is no point taking an
81            // owned self.
82            inner: self.clone(),
83        }
84    }
85
86    /// Returns `true` if this entire list is unique (doesn't share any items with another list).
87    ///
88    /// If this method returns true, [`into_iter_unique`](Self::into_iter_unique) will produce every
89    /// item in the list.
90    pub fn is_unique(&self) -> bool {
91        let mut next = &self.inner;
92        while let Some(node) = next {
93            if !is_unqiue(node) {
94                return false;
95            }
96            next = &node.next.inner;
97        }
98        true
99    }
100
101    /// Returns `true` if the head element of this list is unique.
102    pub fn is_head_unique(&self) -> bool {
103        match &self.inner {
104            Some(node) => is_unqiue(node),
105            None => true,
106        }
107    }
108
109    /// Pops the head element of this list, if it is unique. Otherwise, `self` remains unchanged.
110    pub fn pop_if_unique(&mut self) -> Option<T> {
111        if Rc::get_mut(self.inner.as_mut()?).is_none() {
112            return None;
113        }
114
115        // We've just confirmed that self.inner is Some and that it is unique.
116        let inner = mem::take(&mut self.inner).unwrap();
117        let ConsNode { value, next } = Rc::into_inner(inner).unwrap();
118        self.inner = next.inner;
119
120        Some(value)
121    }
122
123    /// Removes all unique items from this list and returns them as another `ConsBranch`.
124    pub fn split_off_unique(&mut self) -> ConsBranch<T> {
125        let mut node = match &mut self.inner {
126            Some(inner) => inner,
127            // The list is empty.
128            None => return ConsBranch::new(),
129        };
130
131        let mut node_mut = match Rc::get_mut(node) {
132            Some(node_mut) => node_mut,
133            // The list contains items, but none are uniquely referenced.
134            None => return ConsBranch::new(),
135        };
136
137        loop {
138            // We need to borrow the next node once once as a reference and then conditionally, as a
139            // mutable reference.
140            if let Some(true) = node_mut.next.inner.as_ref().map(is_unqiue) {
141                // We know that node_mut.next.inner is Some, but we couldn't borrow it as a
142                // mutable reference until we knew it was unique.
143                node = node_mut.next.inner.as_mut().unwrap();
144            } else {
145                // node_mut.next.inner is either None or a non unique node. For both cases, we take
146                // it as the shared head of the tree and replace it with a None.
147                let shared_head = mem::take(&mut node_mut.next.inner);
148                // We then replace the inner value with it, leaving self as entirely shared and
149                // returning the head of the unique portion.
150                return ConsBranch {
151                    inner: mem::replace(&mut self.inner, shared_head),
152                };
153            }
154
155            // We've already checked that the node is unqiue, and diverged otherwise.
156            // Rc is !Sync, so we don't have to worry about TOCTOU.
157            node_mut = Rc::get_mut(node).unwrap();
158        }
159    }
160
161    /// Produces an [`Iterator<Item = T>`](UniqueIter) over the elements in this list, producing
162    /// owned values until a shared element is found.
163    ///
164    /// This iterator does no cloning and produces owned items by completely ignoring any elements
165    /// that are shared by other lists.
166    ///
167    /// If called on every clone of a single initial `ConsBranch`, every element of the tree will be
168    /// returned by an iterator only once.
169    pub const fn into_iter_unique(self) -> UniqueIter<T> {
170        UniqueIter {
171            inner: self,
172        }
173    }
174}
175
176impl<T: Clone> ConsBranch<T> {
177    /// Pops the head element from this list, cloning if it is shared by another `ConsBranch`.
178    /// Regardless of if a clone is required, the head of this list will be updated.
179    pub fn pop_to_owned(&mut self) -> Option<T> {
180        let inner = mem::take(&mut self.inner);
181
182        match inner {
183            Some(node) => {
184                let ConsNode { value, next } = Rc::unwrap_or_clone(node);
185                self.inner = next.inner;
186                Some(value)
187            },
188            None => {
189                self.inner = inner;
190                None
191            },
192        }
193    }
194
195    /// Produces an [`Iterator<Item = T>`](OwnedIter) over all elements in this list, returning
196    /// owned items by cloning any shared elements.
197    pub const fn into_iter_owned(self) -> OwnedIter<T> {
198        OwnedIter {
199            inner: self,
200        }
201    }
202
203    /// Produces a deep clone of this `ConsBranch`. The result has a clone of every element in this
204    /// list, without sharing any. The result is unique.
205    pub fn deep_clone(&self) -> ConsBranch<T> {
206        let refs: Vec<_> = self.iter().collect();
207
208        refs.into_iter()
209            .rev()
210            .cloned()
211            .collect()
212    }
213}
214
215impl<T> Clone for ConsBranch<T> {
216    /// Creates a cheap (shallow) clone of this `ConsBranch`, with all the same underlying elements.
217    /// After cloning, all elements of the list are considered 'shared' between the original list
218    /// and the clone.
219    fn clone(&self) -> Self {
220        Self {
221            inner: self.inner.clone()
222        }
223    }
224}
225
226fn is_unqiue<T>(value: &Rc<T>) -> bool {
227    Rc::strong_count(value) == 1
228}
229
230impl<T> Default for ConsBranch<T> {
231    fn default() -> Self {
232        Self::new()
233    }
234}
235
236impl<T> FromIterator<T> for ConsBranch<T> {
237    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
238        let mut res = ConsBranch::new();
239        for item in iter {
240            res.push(item);
241        }
242        res
243    }
244}
245
246impl<T> From<Rc<ConsNode<T>>> for ConsBranch<T> {
247    fn from(value: Rc<ConsNode<T>>) -> Self {
248        ConsBranch {
249            inner: Some(value),
250        }
251    }
252}
253
254impl<T> Deref for ConsNode<T> {
255    type Target = T;
256
257    fn deref(&self) -> &Self::Target {
258        &self.value
259    }
260}
261
262impl<T> AsRef<T> for ConsNode<T> {
263    fn as_ref(&self) -> &T {
264        self.deref()
265    }
266}
267
268impl<T: Debug> Debug for ConsBranch<T> {
269    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270        match &self.inner {
271            Some(node) => f.write_fmt(format_args!("{0:?}", node))write!(f, "{:?}", node),
272            None => f.write_fmt(format_args!("()"))write!(f, "()"),
273        }
274    }
275}
276
277impl<T: Debug> Debug for ConsNode<T> {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        match &self.next.inner {
280            Some(node) => f.write_fmt(format_args!("({0:?}->{1:?})", self.value, node))write!(f, "({:?}->{:?})", self.value, node),
281            None => f.write_fmt(format_args!("({0:?})", self.value))write!(f, "({:?})", self.value),
282        }
283    }
284}