orx_iterable/obj_safe/
collection_obj.rs

1use std::boxed::Box;
2
3/// A `CollectionObj` provides the [`boxed_iter`] method which returns a boxed iterator over shared references
4/// of elements of the collection.
5///
6/// It is the object safe counterpart of [`Collection`] trait which can conveniently be made into a trait object.
7///
8/// Note that for collections, `CollectionObj` is implicitly implemented and readily available.
9/// Please refer to [`Collection`] documentation for details of automatic implementations.
10///
11/// In order to use object safe iterables and collections please add `--features std` and use
12/// `use orx_iterable::{*, obj_safe::*}` to import dependencies rather than `use orx_iterable::*`.
13///
14/// [`Iterable`]: crate::Iterable
15/// [`Item`]: crate::obj_safe::CollectionObj::Item
16/// [`boxed_iter`]: crate::obj_safe::CollectionObj::boxed_iter
17/// [`Collection`]: crate::Collection
18///
19/// # Examples
20///
21/// ```
22/// use orx_iterable::obj_safe::*;
23/// use arrayvec::ArrayVec;
24/// use smallvec::{smallvec, SmallVec};
25/// use std::collections::{BTreeSet, BinaryHeap, HashSet, LinkedList, VecDeque};
26///
27/// struct Stats {
28///     count: usize,
29///     mean: i64,
30///     std_dev: i64,
31/// }
32///
33/// /// we need multiple iterations over numbers to compute the stats
34/// fn statistics(numbers: &dyn CollectionObj<Item = i64>) -> Stats {
35///     let count = numbers.boxed_iter().count() as i64;
36///     let sum = numbers.boxed_iter().sum::<i64>();
37///     let mean = sum / count;
38///     let sum_sq_errors: i64 = numbers.boxed_iter().map(|x| (x - mean) * (x - mean)).sum();
39///     let std_dev = f64::sqrt(sum_sq_errors as f64 / (count - 1) as f64) as i64;
40///     Stats {
41///         count: count as usize,
42///         mean,
43///         std_dev,
44///     }
45/// }
46///
47/// // example collections that automatically implement Collection
48///
49/// statistics(&[3, 5, 7]);
50/// statistics(&vec![3, 5, 7]);
51/// statistics(&LinkedList::from_iter([3, 5, 7]));
52/// statistics(&VecDeque::from_iter([3, 5, 7]));
53/// statistics(&HashSet::<_>::from_iter([3, 5, 7]));
54/// statistics(&BTreeSet::<_>::from_iter([3, 5, 7]));
55/// statistics(&BinaryHeap::<_>::from_iter([3, 5, 7]));
56///
57/// let x: SmallVec<[_; 128]> = smallvec![3, 5, 7];
58/// statistics(&x);
59///
60/// let mut x = ArrayVec::<_, 16>::new();
61/// x.extend([3, 5, 7]);
62/// statistics(&x);
63/// ```
64pub trait CollectionObj {
65    /// Type of elements stored by the collection.
66    type Item;
67
68    /// Creates a new iterator in a box yielding references to the elements of the collection; i.e.,
69    /// type of elements is `&Item`.
70    fn boxed_iter(&self) -> Box<dyn Iterator<Item = &Self::Item> + '_>;
71}
72
73impl<X> CollectionObj for X
74where
75    X: IntoIterator,
76    for<'a> &'a X: IntoIterator<Item = &'a <X as IntoIterator>::Item>,
77{
78    type Item = <X as IntoIterator>::Item;
79
80    fn boxed_iter(&self) -> Box<dyn Iterator<Item = &Self::Item> + '_> {
81        Box::new(<&X as IntoIterator>::into_iter(self))
82    }
83}