Skip to main content

devela/data/layout/
collection.rs

1// devela/src/data/layout/collection.rs
2//
3//! Defines the [`DataCollection`] abstract data type.
4//
5// TOC
6// - define DataCollection
7// - impl for devela types:
8//   - Array
9// - impl for reexported types:
10//   - array
11//   - Vec
12//   - VecDeque
13//   - PriorityQueue
14//   - OrderedMap
15//   - OrderedSet
16//   - UnorderedMap
17//   - UnorderedSet
18
19use crate::{
20    Array,
21    NotAvailable::{self, NotImplemented, NotSupported},
22    Storage,
23};
24#[cfg(feature = "alloc")]
25use crate::{BTreeMap, BTreeSet, BinaryHeap, Vec, VecDeque};
26#[cfg(all(feature = "alloc", feature = "dep_hashbrown"))]
27use crate::{HashMap, HashSet};
28
29type Result<T> = crate::Result<T, NotAvailable>;
30
31#[doc = crate::_tags!(data_structure)]
32/// An abstract *collection* data type.
33#[doc = crate::_doc_meta!{location("data/layout")}]
34///
35/// By default returns [`NotImplemented`] for every method.
36#[rustfmt::skip] #[allow(unused_variables)]
37pub trait DataCollection {
38    /// The element type of the collection.
39    type Element;
40
41    /// Returns the reserved capacity for elements in the collection.
42    fn collection_capacity(&self) -> Result<usize> { Err(NotImplemented) }
43    /// Returns the current number of elements in the collection.
44    fn collection_len(&self) -> Result<usize> { Err(NotImplemented) }
45
46    /// Returns `true` if the collection is empty, `false` if it's not.
47    fn collection_is_empty(&self) -> Result<bool> { Err(NotImplemented) }
48    /// Returns `true` if the collection is full, `false` if it's not.
49    fn collection_is_full(&self) -> Result<bool> { Err(NotImplemented) }
50
51    /// Returns `true` if the collection contains the given `element`.
52    fn collection_contains(&self, element: Self::Element) -> Result<bool>
53    where Self::Element: PartialEq { Err(NotImplemented) }
54    /// Counts the number of times a given `element` appears in the collection.
55    fn collection_count(&self, element: &Self::Element) -> Result<usize>
56    where Self::Element: PartialEq { Err(NotImplemented) }
57}
58
59/* impl for devela types */
60
61#[rustfmt::skip]
62impl<T, const LEN: usize, S: Storage> DataCollection for Array<T, LEN, S> {
63    type Element = T;
64    /// The capacity of a fixed-size array is always equal to its length.
65    fn collection_capacity(&self) -> Result<usize> { Ok(LEN) }
66    fn collection_len(&self) -> Result<usize> { Ok(LEN) }
67    /// Returns [`NotSupported`] since a fixed-size array is never empty or full.
68    fn collection_is_empty(&self) -> Result<bool> { Err(NotSupported) }
69    /// Returns [`NotSupported`] since a fixed-size array is never empty or full.
70    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
71    fn collection_contains(&self, element: Self::Element) -> Result<bool> where T: PartialEq {
72        Ok(self.contains(&element))
73    }
74    fn collection_count(&self, element: &Self::Element) -> Result<usize> where T: PartialEq {
75        Ok(self.iter().filter(|&e| e == element).count())
76    }
77}
78
79/* impl for reexported types */
80
81// array
82#[rustfmt::skip]
83impl<T, const N: usize> DataCollection for [T; N] {
84    type Element = T;
85    // For a fixed-size array, the capacity is always the length of the array.
86    fn collection_capacity(&self) -> Result<usize> { Ok(N) }
87    fn collection_len(&self) -> Result<usize> { Ok(N) }
88    // A fixed-size array is never empty nor full.
89    /// Returns [`NotSupported`] since a fixed-size array is never empty or full.
90    fn collection_is_empty(&self) -> Result<bool> { Err(NotSupported) }
91    /// Returns [`NotSupported`] since a fixed-size array is never empty or full.
92    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
93
94    fn collection_contains(&self, element: Self::Element) -> Result<bool> where T: PartialEq {
95        Ok(self.contains(&element))
96    }
97    fn collection_count(&self, element: &Self::Element) -> Result<usize> where T: PartialEq {
98        Ok(self.iter().filter(|&e| e == element).count())
99    }
100}
101
102#[rustfmt::skip]
103#[cfg(feature = "alloc")]
104impl<T> DataCollection for Vec<T> {
105    type Element = T;
106    fn collection_capacity(&self) -> Result<usize> { Ok(self.capacity()) }
107    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
108    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
109    fn collection_is_full(&self) -> Result<bool> { Ok(self.len() >= self.capacity()) }
110    fn collection_contains(&self, element: Self::Element) -> Result<bool> where T: PartialEq {
111        Ok(self.contains(&element))
112    }
113    fn collection_count(&self, element: &Self::Element) -> Result<usize> where T: PartialEq {
114        Ok(self.iter().filter(|&e| e == element).count())
115    }
116}
117
118#[rustfmt::skip]
119#[cfg(feature = "alloc")]
120impl<T> DataCollection for VecDeque<T> {
121    type Element = T;
122    fn collection_capacity(&self) -> Result<usize> { Ok(self.capacity()) }
123    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
124    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
125    fn collection_is_full(&self) -> Result<bool> { Ok(self.len() >= self.capacity()) }
126    fn collection_contains(&self, element: Self::Element) -> Result<bool> where T: PartialEq {
127        Ok(self.contains(&element))
128    }
129    fn collection_count(&self, element: &Self::Element) -> Result<usize> where T: PartialEq {
130        Ok(self.iter().filter(|&e| e == element).count())
131    }
132}
133
134#[rustfmt::skip]
135#[cfg(feature = "alloc")]
136impl<T> DataCollection for BinaryHeap<T> {
137    type Element = T;
138    fn collection_capacity(&self) -> Result<usize> { Ok(self.capacity()) }
139    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
140    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
141    fn collection_is_full(&self) -> Result<bool> { Ok(self.len() >= self.capacity()) }
142    /// Returns [`NotSupported`].
143    fn collection_contains(&self, _: Self::Element) -> Result<bool> { Err(NotSupported) }
144    /// Returns [`NotSupported`].
145    fn collection_count(&self, _: &Self::Element) -> Result<usize> { Err(NotSupported) }
146}
147
148#[rustfmt::skip]
149#[cfg(feature = "alloc")]
150impl<K, V> DataCollection for BTreeMap<K, V> {
151    type Element = V;
152    /// Returns [`NotSupported`].
153    fn collection_capacity(&self) -> Result<usize> { Err(NotSupported) }
154    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
155    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
156    /// Returns [`NotSupported`].
157    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
158    fn collection_contains(&self, element: Self::Element) -> Result<bool> where V: PartialEq {
159        Ok(self.values().any(|value| *value == element))
160    }
161    fn collection_count(&self, element: &Self::Element) -> Result<usize> where V: PartialEq {
162        Ok(self.values().filter(|&value| value == element).count())
163    }
164}
165#[rustfmt::skip]
166#[cfg(feature = "alloc")]
167impl<V> DataCollection for BTreeSet<V> {
168    type Element = V;
169    /// Returns [`NotSupported`].
170    fn collection_capacity(&self) -> Result<usize> { Err(NotSupported) }
171    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
172    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
173    /// Returns [`NotSupported`].
174    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
175    /// This is less efficent than [`BTreeSet::contains`] for not having [`Ord`].
176    fn collection_contains(&self, element: Self::Element) -> Result<bool> where V: PartialEq {
177        Ok(self.iter().any(|value| *value == element))
178    }
179    /// This is less efficent than [`BTreeSet::contains`] for not having [`Ord`].
180    fn collection_count(&self, element: &Self::Element) -> Result<usize> where V: PartialEq {
181        Ok(usize::from(self.iter().any(|e| e == element)))
182    }
183}
184
185#[rustfmt::skip]
186#[cfg(all(feature = "alloc", feature = "dep_hashbrown"))]
187impl<K, V> DataCollection for HashMap<K, V> {
188    type Element = V;
189    /// Returns [`NotSupported`].
190    fn collection_capacity(&self) -> Result<usize> { Err(NotSupported) }
191    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
192    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
193    /// Returns [`NotSupported`].
194    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
195    fn collection_contains(&self, element: Self::Element) -> Result<bool> where V: PartialEq {
196        Ok(self.values().any(|value| *value == element))
197    }
198    fn collection_count(&self, element: &Self::Element) -> Result<usize> where V: PartialEq {
199        Ok(self.values().filter(|&value| value == element).count())
200    }
201}
202#[rustfmt::skip]
203#[cfg(all(feature = "alloc", feature = "dep_hashbrown"))]
204impl<V> DataCollection for HashSet<V> {
205    type Element = V;
206    fn collection_capacity(&self) -> Result<usize> { Ok(self.capacity()) }
207    fn collection_len(&self) -> Result<usize> { Ok(self.len()) }
208    fn collection_is_empty(&self) -> Result<bool> { Ok(self.is_empty()) }
209    fn collection_is_full(&self) -> Result<bool> { Err(NotSupported) }
210    /// This is less efficent than [`HashSet::contains`] for not having [`Hash`] and [`Eq`].
211    fn collection_contains(&self, element: Self::Element) -> Result<bool> where V: PartialEq {
212        Ok(self.iter().any(|value| *value == element))
213    }
214    /// This is less efficent than [`HashSet::contains`] for not having [`Hash`] and [`Eq`].
215    fn collection_count(&self, element: &Self::Element) -> Result<usize> where V: PartialEq {
216        Ok(usize::from(self.iter().any(|e| e == element)))
217    }
218}