1use alloc::vec::Vec;
4
5#[derive(Debug, Clone, Eq)]
10pub enum List<'a, T> {
11 Borrowed(&'a [&'a T]),
13 Owned(Vec<T>),
15}
16
17impl<'a, T> List<'a, T> {
18 pub fn iter(&self) -> impl Iterator<Item = &T> {
20 match self {
21 List::Borrowed(slice) => ListIter::Borrowed(slice.iter()),
22 List::Owned(vec) => ListIter::Owned(vec.iter()),
23 }
24 }
25
26 pub fn len(&self) -> usize {
28 match self {
29 List::Borrowed(slice) => slice.len(),
30 List::Owned(vec) => vec.len(),
31 }
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.len() == 0
37 }
38
39 pub const fn as_borrowed(&self) -> Option<&[&T]> {
41 match self {
42 List::Borrowed(slice) => Some(slice),
43 List::Owned(_) => None,
44 }
45 }
46
47 pub fn as_owned(&self) -> Option<&Vec<T>> {
49 match self {
50 List::Borrowed(_) => None,
51 List::Owned(vec) => Some(vec),
52 }
53 }
54}
55
56enum ListIter<'a, T> {
58 Borrowed(core::slice::Iter<'a, &'a T>),
59 Owned(core::slice::Iter<'a, T>),
60}
61
62impl<'a, T> Iterator for ListIter<'a, T> {
63 type Item = &'a T;
64
65 fn next(&mut self) -> Option<Self::Item> {
66 match self {
67 ListIter::Borrowed(iter) => iter.next().copied(),
68 ListIter::Owned(iter) => iter.next(),
69 }
70 }
71}
72
73impl<'a, T> Default for List<'a, T> {
74 fn default() -> Self {
75 List::Borrowed(&[])
76 }
77}
78
79impl<'a, T> From<Vec<T>> for List<'a, T> {
80 fn from(vec: Vec<T>) -> Self {
81 List::Owned(vec)
82 }
83}
84
85impl<'a, T> From<&'a [&'a T]> for List<'a, T> {
86 fn from(slice: &'a [&'a T]) -> Self {
87 List::Borrowed(slice)
88 }
89}
90
91impl<'a, T> PartialEq for List<'a, T>
92where
93 T: PartialEq,
94{
95 fn eq(&self, other: &Self) -> bool {
96 if self.len() != other.len() {
97 return false;
98 }
99
100 self.iter().zip(other.iter()).all(|(a, b)| a == b)
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use alloc::{
107 string::{String, ToString},
108 vec,
109 };
110
111 use super::*;
112
113 #[test]
114 fn list_borrowed() {
115 static ITEM_ONE: &str = "one";
116 static ITEM_TWO: &str = "two";
117 static ITEM_THREE: &str = "three";
118 static ITEMS: [&'static &str; 3] = [&ITEM_ONE, &ITEM_TWO, &ITEM_THREE];
119 let list: List<'_, &str> = List::Borrowed(&ITEMS);
120
121 assert_eq!(list.len(), 3);
122 assert!(!list.is_empty());
123
124 let expected = ["one", "two", "three"];
125 let mut actual = Vec::<&str>::new();
126 for item in list.iter() {
127 actual.push(*item);
128 }
129 assert_eq!(actual.as_slice(), &expected);
130 }
131
132 #[test]
133 fn list_owned() {
134 let vec = vec!["one".to_string(), "two".to_string(), "three".to_string()];
135 let list: List<'_, String> = List::from(vec);
136
137 assert_eq!(list.len(), 3);
138 assert!(!list.is_empty());
139
140 let collected: Vec<_> = list.iter().map(|s| s.as_str()).collect();
141 assert_eq!(collected, vec!["one", "two", "three"]);
142 }
143
144 #[test]
145 fn list_partial_eq_cross_variant() {
146 static ITEM_ONE: &str = "one";
148 static ITEM_TWO: &str = "two";
149 static ITEM_THREE: &str = "three";
150 static REFS: [&'static &str; 3] = [&ITEM_ONE, &ITEM_TWO, &ITEM_THREE];
151 let borrowed_list: List<'_, &str> = List::Borrowed(&REFS);
152
153 let owned_list: List<'_, &str> = List::Owned(vec!["one", "two", "three"]);
154 assert_eq!(borrowed_list, owned_list);
155 assert_eq!(owned_list, borrowed_list);
156
157 static OTHER_REFS: [&'static &str; 2] = [&ITEM_ONE, &ITEM_TWO];
159 let different_borrowed: List<'_, &str> = List::Borrowed(&OTHER_REFS);
160 assert_ne!(borrowed_list, different_borrowed);
161
162 let different_owned: List<'_, &str> = List::Owned(vec!["one", "two"]);
163 assert_ne!(borrowed_list, different_owned);
164 }
165}