]>
Commit | Line | Data |
---|---|---|
94b46f34 XL |
1 | //! A singly-linked list. |
2 | //! | |
3 | //! Using this data structure only makes sense under very specific | |
4 | //! circumstances: | |
5 | //! | |
6 | //! - If you have a list that rarely stores more than one element, then this | |
7 | //! data-structure can store the element without allocating and only uses as | |
8 | //! much space as a `Option<(T, usize)>`. If T can double as the `Option` | |
9 | //! discriminant, it will even only be as large as `T, usize`. | |
10 | //! | |
11 | //! If you expect to store more than 1 element in the common case, steer clear | |
12 | //! and use a `Vec<T>`, `Box<[T]>`, or a `SmallVec<T>`. | |
13 | ||
416331ca XL |
14 | #[cfg(test)] |
15 | mod tests; | |
16 | ||
e74abb32 | 17 | #[derive(Clone)] |
94b46f34 | 18 | pub struct TinyList<T: PartialEq> { |
60c5eb7d | 19 | head: Option<Element<T>>, |
94b46f34 XL |
20 | } |
21 | ||
22 | impl<T: PartialEq> TinyList<T> { | |
94b46f34 XL |
23 | #[inline] |
24 | pub fn new() -> TinyList<T> { | |
60c5eb7d | 25 | TinyList { head: None } |
94b46f34 XL |
26 | } |
27 | ||
28 | #[inline] | |
29 | pub fn new_single(data: T) -> TinyList<T> { | |
60c5eb7d | 30 | TinyList { head: Some(Element { data, next: None }) } |
94b46f34 XL |
31 | } |
32 | ||
33 | #[inline] | |
34 | pub fn insert(&mut self, data: T) { | |
60c5eb7d | 35 | self.head = Some(Element { data, next: self.head.take().map(Box::new) }); |
94b46f34 XL |
36 | } |
37 | ||
38 | #[inline] | |
39 | pub fn remove(&mut self, data: &T) -> bool { | |
b7449926 | 40 | self.head = match self.head { |
60c5eb7d | 41 | Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x), |
b7449926 XL |
42 | Some(ref mut head) => return head.remove_next(data), |
43 | None => return false, | |
94b46f34 | 44 | }; |
b7449926 | 45 | true |
94b46f34 XL |
46 | } |
47 | ||
48 | #[inline] | |
49 | pub fn contains(&self, data: &T) -> bool { | |
e1599b0c XL |
50 | let mut elem = self.head.as_ref(); |
51 | while let Some(ref e) = elem { | |
52 | if &e.data == data { | |
53 | return true; | |
54 | } | |
55 | elem = e.next.as_ref().map(|e| &**e); | |
94b46f34 | 56 | } |
e1599b0c | 57 | false |
94b46f34 XL |
58 | } |
59 | ||
60 | #[inline] | |
61 | pub fn len(&self) -> usize { | |
e1599b0c XL |
62 | let (mut elem, mut count) = (self.head.as_ref(), 0); |
63 | while let Some(ref e) = elem { | |
64 | count += 1; | |
65 | elem = e.next.as_ref().map(|e| &**e); | |
94b46f34 | 66 | } |
e1599b0c | 67 | count |
94b46f34 XL |
68 | } |
69 | } | |
70 | ||
e74abb32 | 71 | #[derive(Clone)] |
94b46f34 XL |
72 | struct Element<T: PartialEq> { |
73 | data: T, | |
74 | next: Option<Box<Element<T>>>, | |
75 | } | |
76 | ||
77 | impl<T: PartialEq> Element<T> { | |
94b46f34 | 78 | fn remove_next(&mut self, data: &T) -> bool { |
60c5eb7d XL |
79 | let mut n = self; |
80 | loop { | |
81 | match n.next { | |
82 | Some(ref mut next) if next.data == *data => { | |
83 | n.next = next.next.take(); | |
84 | return true; | |
85 | } | |
86 | Some(ref mut next) => n = next, | |
87 | None => return false, | |
88 | } | |
89 | } | |
94b46f34 | 90 | } |
94b46f34 | 91 | } |