1use std::borrow::Cow;
2
3pub enum Collection<'c, T: std::ops::Deref + 'static>
55where [T]: ToOwned {
56 Owned(Cow<'c, [T]>),
58 Borrowed(Cow<'c, [&'c T]>),
60 Ref(Cow<'c, [&'c T::Target]>),
62 OwnedString(Cow<'c, [String]>),
64 BorrowedString(Cow<'c, [&'c String]>),
66 RefStr(Cow<'c, [&'c str]>),
68}
69
70impl<'c, T: std::ops::Deref> Collection<'c, T>
71where
72 [T]: ToOwned,
73 for<'t> &'t T::Target: From<&'t str>,
74{
75 pub const EMPTY: Self = Self::Ref(Cow::Borrowed(&[]));
77
78 pub fn iter(&self) -> CollectionIter<'_, T> {
92 match self {
93 Collection::Owned(v) => CollectionIter {
94 inner: CollectionIterInner::Owned(v.as_ref()),
95 },
96 Collection::Borrowed(v) => CollectionIter {
97 inner: CollectionIterInner::Borrowed(v.as_ref()),
98 },
99 Collection::Ref(v) => CollectionIter {
100 inner: CollectionIterInner::Ref(v.as_ref()),
101 },
102 Collection::OwnedString(v) => {
103 let iter = Box::new(v.iter().map(|v| <_>::from(v.as_str())));
104 CollectionIter {
105 inner: CollectionIterInner::String(iter),
106 }
107 }
108 Collection::BorrowedString(v) => {
109 let iter = Box::new(v.iter().map(|&v| <_>::from(v.as_str())));
110 CollectionIter {
111 inner: CollectionIterInner::String(iter),
112 }
113 }
114 Collection::RefStr(v) => {
115 let iter = Box::new(v.iter().map(move |&v| <_>::from(v)));
116 CollectionIter {
117 inner: CollectionIterInner::String(iter),
118 }
119 }
120 }
121 }
122
123 pub fn into_vec(self) -> Vec<T>
134 where
135 [T]: ToOwned<Owned = Vec<T>>,
136 T: 'static + Clone,
137 for<'d> T: From<&'d <T as std::ops::Deref>::Target>,
138 for<'d> T: From<&'d str>, {
139 match self {
140 Collection::Owned(v) => v.into_owned(),
141 Collection::Borrowed(v) => v.iter().map(|v| (*v).clone()).collect(),
142 Collection::Ref(v) => v.iter().map(|&v| <T>::from(v)).collect(),
143 Collection::OwnedString(v) => v.iter().map(|v| <T>::from(v.as_str())).collect(),
144 Collection::BorrowedString(v) => v.iter().map(|v| <T>::from(v.as_str())).collect(),
145 Collection::RefStr(v) => v.iter().map(|&v| <T>::from(v)).collect(),
146 }
147 }
148
149 fn index(&'c self, range: impl std::ops::RangeBounds<usize>) -> Option<Collection<'c, T>> {
150 let range = (range.start_bound().cloned(), range.end_bound().cloned());
151 let new: Collection<'_, T> = match self {
152 Collection::Owned(v) => Collection::Owned(Cow::Borrowed(v.get(range)?)),
153 Collection::Borrowed(v) => Collection::Borrowed(Cow::Borrowed(v.get(range)?)),
154 Collection::Ref(v) => Collection::Ref(Cow::Borrowed(v.get(range)?)),
155 Collection::OwnedString(v) => Collection::OwnedString(Cow::Borrowed(v.get(range)?)),
156 Collection::BorrowedString(v) => {
157 Collection::BorrowedString(Cow::Borrowed(v.get(range)?))
158 }
159 Collection::RefStr(v) => Collection::RefStr(Cow::Borrowed(v.get(range)?)),
160 };
161 Some(new)
162 }
163
164 pub fn chunks(&'c self, chunk_size: usize) -> impl Iterator<Item = Collection<'c, T>> + 'c {
166 let len = self.iter().len();
167 let mut start = 0;
168 std::iter::from_fn(move || {
169 if start >= len {
170 return None;
171 }
172 let end = start + chunk_size;
173 let end = if end > len { len } else { end };
174 let range = start..end;
175 start = end;
176 self.index(range)
177 })
178 }
179
180 pub fn len(&self) -> usize {
182 match self {
183 Collection::Owned(v) => v.len(),
184 Collection::Borrowed(v) => v.len(),
185 Collection::Ref(v) => v.len(),
186 Collection::OwnedString(v) => v.len(),
187 Collection::BorrowedString(v) => v.len(),
188 Collection::RefStr(v) => v.len(),
189 }
190 }
191
192 pub fn is_empty(&self) -> bool { self.len() == 0 }
194}
195
196impl<T: std::ops::Deref + std::fmt::Debug> std::fmt::Debug for Collection<'_, T>
197where
198 [T]: ToOwned,
199 <[T] as ToOwned>::Owned: std::fmt::Debug,
200 T: std::fmt::Debug,
201 T::Target: std::fmt::Debug,
202{
203 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
204 match self {
205 Self::Owned(owned) => f.debug_tuple("Owned").field(owned).finish(),
206 Self::Borrowed(borrowed) => f.debug_tuple("Borrowed").field(borrowed).finish(),
207 Self::Ref(ref_) => f.debug_tuple("Ref").field(ref_).finish(),
208 Self::OwnedString(owned) => f.debug_tuple("OwnedString").field(owned).finish(),
209 Self::BorrowedString(borrowed) => {
210 f.debug_tuple("BorrowedString").field(borrowed).finish()
211 }
212 Self::RefStr(ref_) => f.debug_tuple("RefStr").field(ref_).finish(),
213 }
214 }
215}
216
217impl<'a, T: std::ops::Deref, A: std::ops::Deref> FromIterator<A> for Collection<'a, T>
218where
219 [T]: ToOwned,
220 [A]: ToOwned,
221 Collection<'a, T>: From<Vec<A>>,
222 T: 'static,
223{
224 fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
225 let v: Vec<_> = iter.into_iter().collect();
226 Collection::from(v)
227 }
228}
229
230impl<T: std::ops::Deref + Clone> From<Vec<T>> for Collection<'_, T>
231where
232 [T]: ToOwned,
233 T: 'static,
234{
235 fn from(v: Vec<T>) -> Self { Self::Owned(Cow::from(v)) }
236}
237
238impl<'c, T: std::ops::Deref + Clone> From<Vec<&'c T>> for Collection<'c, T>
239where
240 [T]: ToOwned,
241 T: 'static,
242{
243 fn from(v: Vec<&'c T>) -> Self { Self::Borrowed(Cow::from(v)) }
244}
245
246impl<'c, T: std::ops::Deref + Clone> From<&'c [T]> for Collection<'c, T>
248where
249 [T]: ToOwned,
250 T: 'static,
251{
252 fn from(v: &'c [T]) -> Self { Self::Owned(Cow::Borrowed(v)) }
253}
254
255impl<'c, T: std::ops::Deref + Clone> From<&'c [&'c T]> for Collection<'c, T>
256where
257 [T]: ToOwned,
258 T: 'static,
259{
260 fn from(v: &'c [&'c T]) -> Self { Self::Borrowed(Cow::from(v)) }
261}
262
263impl<'s, 'c, T: std::ops::Deref> IntoIterator for &'s Collection<'c, T>
264where
265 [T]: ToOwned,
266 for<'t> &'t T::Target: From<&'t str>,
267 's: 'c,
268{
269 type IntoIter = CollectionIter<'c, T>;
270 type Item = &'c T::Target;
271
272 fn into_iter(self) -> Self::IntoIter { self.iter() }
273}
274
275pub struct CollectionIter<'c, T: std::ops::Deref>
277where [T]: ToOwned {
278 inner: CollectionIterInner<'c, T>,
279}
280
281enum CollectionIterInner<'c, T: std::ops::Deref>
282where [T]: ToOwned {
283 Ref(&'c [&'c T::Target]),
284 Borrowed(&'c [&'c T]),
285 Owned(&'c [T]),
286 String(Box<dyn std::iter::ExactSizeIterator<Item = &'c T::Target> + 'c>),
287}
288
289impl<'c, T: std::ops::Deref> Iterator for CollectionIter<'c, T>
290where
291 [T]: ToOwned,
292 'c: 'c,
293{
294 type Item = &'c T::Target;
295
296 fn next(&mut self) -> Option<Self::Item> {
297 match &mut self.inner {
298 CollectionIterInner::Ref(ref_) => {
299 let v = ref_.first()?;
300 *ref_ = &ref_[1..];
301 Some(v)
302 }
303 CollectionIterInner::Borrowed(borrowed) => {
304 let v = borrowed.first()?;
305 *borrowed = &borrowed[1..];
306 Some(v)
307 }
308 CollectionIterInner::Owned(owned) => {
309 let v = owned.first()?;
310 *owned = &owned[1..];
311 Some(v)
312 }
313 CollectionIterInner::String(b) => b.next(),
314 }
315 }
316
317 fn size_hint(&self) -> (usize, Option<usize>) { (self.len(), Some(self.len())) }
318
319 fn count(self) -> usize
320 where Self: Sized {
321 self.len()
322 }
323
324 fn last(self) -> Option<Self::Item>
325 where Self: Sized {
326 match self.inner {
327 CollectionIterInner::Ref(v) => v.last().copied(),
328 CollectionIterInner::Borrowed(v) => v.last().map(|v| v.deref()),
329 CollectionIterInner::Owned(v) => v.last().map(|v| v.deref()),
330 CollectionIterInner::String(b) => b.last(),
331 }
332 }
333}
334
335impl<T: std::ops::Deref> CollectionIter<'_, T>
336where [T]: ToOwned
337{
338 fn len(&self) -> usize {
339 match self.inner {
340 CollectionIterInner::Ref(v) => v.len(),
341 CollectionIterInner::Borrowed(v) => v.len(),
342 CollectionIterInner::Owned(v) => v.len(),
343 CollectionIterInner::String(ref b) => b.len(),
344 }
345 }
346}
347
348#[cfg(feature = "serde")]
349impl<'a, 'de: 'a, T: std::ops::Deref + serde::Deserialize<'de> + Clone> serde::Deserialize<'de>
350 for Collection<'a, T>
351where
352 [T]: ToOwned,
353 &'a T::Target: serde::Deserialize<'de>,
354{
355 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
356 where D: serde::Deserializer<'de> {
357 let collection: Vec<T> = serde::Deserialize::deserialize(deserializer)?;
358 Ok(Collection::Owned(Cow::from(collection)))
359 }
360}
361
362#[cfg(feature = "serde")]
363impl<T: std::ops::Deref> serde::Serialize for Collection<'_, T>
364where
365 [T]: ToOwned,
366 for<'s> &'s T::Target: serde::Serialize,
367 for<'s> &'s T::Target: From<&'s str>,
368{
369 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
370 where S: serde::Serializer {
371 serializer.collect_seq(self.iter())
372 }
373}
374
375impl<T: Clone + std::ops::Deref> Clone for Collection<'_, T>
377where [T]: ToOwned
378{
379 fn clone(&self) -> Self {
380 match self {
381 Collection::Owned(v) => Collection::Owned(v.clone()),
382 Collection::Borrowed(v) => Collection::Borrowed(v.clone()),
383 Collection::Ref(v) => Collection::Ref(v.clone()),
384 Collection::OwnedString(v) => Collection::OwnedString(v.clone()),
385 Collection::BorrowedString(v) => Collection::BorrowedString(v.clone()),
386 Collection::RefStr(v) => Collection::RefStr(v.clone()),
387 }
388 }
389}
390
391impl<T: std::ops::Deref> PartialEq for Collection<'_, T>
392where
393 [T]: ToOwned,
394 T: PartialEq,
395 T::Target: PartialEq,
396 T: std::cmp::PartialEq<T::Target>,
397 for<'s> &'s T::Target: From<&'s str>,
398 T::Target: std::fmt::Debug,
399 T: std::fmt::Debug,
400{
401 #[rustfmt::skip]
402 fn eq(&self, other: &Self) -> bool {
403 use self::Collection::*;
404 match (self, other) {
405 (Owned(v), Owned(v2)) => v == v2,
406 (Borrowed(v), Borrowed(v2)) => v == v2,
407 (Ref(v), Ref(v2)) => v == v2,
408 (OwnedString(v), OwnedString(v2)) => v == v2,
409 (BorrowedString(v), BorrowedString(v2)) => v == v2,
410 (RefStr(v), RefStr(v2)) => v == v2,
411
412 (Borrowed(borrowed), Ref(ref_)) | (Ref(ref_), Borrowed(borrowed)) => borrowed == ref_,
415
416 _ => {
418 let _: Vec<_> = dbg!(self.iter().collect());
419 let _: Vec<_> = dbg!(other.iter().collect());
420 dbg!(self.iter().eq(other.iter()))},
421 }
422 }
423}
424
425impl<T: std::ops::Deref> Eq for Collection<'_, T>
426where
427 [T]: ToOwned,
428 T: PartialEq,
429 T::Target: PartialEq,
430 T: std::cmp::PartialEq<T::Target>,
431 for<'s> &'s T::Target: From<&'s str>,
432 T::Target: std::fmt::Debug,
433 T: std::fmt::Debug,
434{
435}
436
437impl<T: std::ops::Deref> Default for Collection<'_, T>
438where
439 [T]: ToOwned,
440 <[T] as ToOwned>::Owned: Default,
441{
442 fn default() -> Self { Self::Ref(Cow::default()) }
443}
444
445#[cfg(test)]
446mod test {
447 use super::*;
448
449 #[test]
450 fn test_collection() {
451 let owned: Vec<_> = vec![crate::UserId::from("1234"), crate::UserId::from("5678")];
452 let borrow = (&crate::UserId::from("1234"), &crate::UserId::from("5678"));
453 let borrowed: Vec<_> = vec![borrow.0, borrow.1];
454 let ref_: Vec<_> = vec![
455 crate::UserIdRef::from_str("1234"),
456 crate::UserIdRef::from_str("5678"),
457 ];
458 let collection_owned = Collection::from(owned.clone());
459 let collection_borrowed = Collection::from(borrowed.clone());
460 let collection_ref = Collection::from(ref_);
461 assert_eq!(collection_owned, collection_borrowed);
462 assert_eq!(collection_owned, collection_ref);
463 assert_eq!(collection_borrowed, collection_ref);
464 assert_eq!(collection_owned.iter().collect::<Vec<_>>(), owned);
465 assert_eq!(collection_borrowed.iter().collect::<Vec<_>>(), owned);
466 assert_eq!(collection_ref.iter().collect::<Vec<_>>(), owned);
467 assert_eq!(collection_ref.iter().last(), Some("5678".into()));
468 }
469
470 #[test]
471 fn test_collection_stringed() {
472 let owned_s: Vec<_> = vec![String::from("1234"), String::from("5678")];
473 let borrow_s = (&String::from("1234"), &String::from("5678"));
474 let borrowed_s: Vec<_> = vec![borrow_s.0, borrow_s.1];
475 let ref_s: Vec<_> = vec!["1234", "5678"];
476 let ref_: Vec<_> = vec![
477 crate::UserIdRef::from_str("1234"),
478 crate::UserIdRef::from_str("5678"),
479 ];
480 let collection_owned_s: Collection<crate::UserId> = Collection::from(owned_s.clone());
481 let collection_borrowed_s: Collection<crate::UserId> = Collection::from(borrowed_s.clone());
482 let collection_ref_s: Collection<crate::UserId> = Collection::from(ref_s);
483 let collection_ref: Collection<crate::UserId> = Collection::from(ref_);
484 assert_eq!(collection_owned_s, collection_borrowed_s);
485 assert_eq!(collection_owned_s, collection_ref_s);
486 assert_eq!(collection_borrowed_s, collection_ref_s);
487 assert_eq!(collection_ref, collection_ref_s);
488 assert_eq!(collection_ref_s.iter().last(), Some("5678".into()));
489 }
490}