cc_traits/
lib.rs

1//! This crate provide traits to describe common operations available on data structures.
2//! This is particularly useful when building new types on top of generic data structures without relying on the actual implementation of the underlying data structure.
3//!
4//! Here is an example of the kind of traits provided by this crate:
5//! ```rust
6//! # use cc_traits::Collection;
7//! /// Mutable collection where new elements can be inserted.
8//! pub trait Insert: Collection {
9//!     /// The output of the insertion function.
10//!     type Output;
11//!
12//!     /// Insert a new element in the collection.
13//!     fn insert(&mut self, element: Self::Item) -> Self::Output;
14//! }
15//! ```
16//!
17//! # Usage
18//!
19//! Such traits can be used to define collections with special properties,
20//! independently of the actual internal data structure.
21//! For instance the following code defines an `Ordered<S>` stack collection,
22//! guarantying the well-sortedness of the elements in the stack.
23//!
24//! ```rust
25//! use cc_traits::{
26//!     Collection,
27//!     Back,
28//!     PushBack
29//! };
30//!
31//! /// Ordered stack.
32//! pub struct Ordered<S> {
33//!     inner: S
34//! }
35//!
36//! impl<S> Ordered<S> {
37//!     pub fn new() -> Self where S: Default {
38//!         Ordered {
39//!             inner: S::default()
40//!         }
41//!     }
42//! }
43//!
44//! impl<S> Ordered<S> {
45//!     /// Push the given element on the stack iff it is grater or equal
46//!     /// to every other element already in the stack.
47//!     pub fn try_push<T>(&mut self, element: T) -> Result<(), T>
48//!     where
49//!         T: PartialOrd,
50//!         S: Collection<Item=T> + Back + PushBack, // `S` must be a stack providing `back` and `push_back`.
51//!         for<'a> S::ItemRef<'a>: PartialOrd<&'a T> // The reference type must be comparable with other reference types.
52//!     {
53//!         if self.inner.back().map(|back| back <= &element).unwrap_or(true) {
54//!             self.inner.push_back(element);
55//!             Ok(())
56//!         } else {
57//!             Err(element)
58//!         }
59//!     }
60//! }
61//!
62//! #[cfg(feature = "std")]
63//! fn ordered_stack_usage<S>()
64//! where
65//!     S: Default + Collection<Item = i32> + Back + PushBack,
66//!     for<'a> S::ItemRef<'a>: PartialOrd<&'a i32>,
67//! {
68//!     let mut ordered: Ordered<S> = Ordered::new();
69//!     assert!(ordered.try_push(1).is_ok());
70//!     assert!(ordered.try_push(2).is_ok());
71//!     assert!(ordered.try_push(0).is_err());
72//! }
73//!
74//! #[cfg(feature = "std")]
75//! ordered_stack_usage::<Vec<i32>>(); // a `Vec` is a stack so it works.
76//!
77//! #[cfg(feature = "std")]
78//! use std::collections::VecDeque;
79//! #[cfg(feature = "std")]
80//! ordered_stack_usage::<VecDeque<i32>>(); // a `VecDeque` is also a stack.
81//! ```
82//!
83//! # Trait aliases
84//!
85//! By enabling the `nightly` you can get access to
86//! some trait alias definitions that can be useful to reduce the
87//! verbosity of your code.
88//! Here is an example of such aliases defining the common interface of stacks:
89//! ```ignore
90//! pub trait Stack<T> = Collection<Item=T> + Len + Back;
91//! pub trait StackMut<T> = Stack<T> + BackMut + PushBack + PopBack;
92//! ```
93//!
94//! As of version 0.8.0, those traits are also available without the `nightly`
95//! feature as regular trait definitions.
96//!
97//! # Standard library
98//!
99//! By default, all the traits defined in this crate are implemented (when relevant)
100//! for the standard library collections.
101//! You can disable it by using the `nostd` feature.
102//!
103//! # Foreign implementations
104//!
105//! In addition to the standard library,
106//! traits are implemented for
107//! some popular crates if you enable the feature of the same name.
108//! Here are the supported crates:
109//!
110//!   - [`slab`](https://crates.io/crates/slab) providing the `Slab` collection.
111//!   - [`smallvec`](https://crates.io/crates/smallvec) providing the `SmallVec` collection.
112//!   - [`serde_json`](https://crates.io/crates/serde_json) providing the `Map<String, Value>` collection for JSON objects.
113//!   - [`ijson`](https://crates.io/crates/ijson) providing the `IObject` and `IArray` collections.
114#![cfg_attr(not(feature = "std"), no_std)]
115#![cfg_attr(feature = "nightly", feature(trait_alias))]
116
117#[cfg(feature = "alloc")]
118extern crate alloc;
119extern crate core;
120
121mod impls;
122mod macros;
123
124#[cfg(feature = "nightly")]
125mod alias;
126#[cfg(feature = "nightly")]
127pub use alias::*;
128
129#[cfg(not(feature = "nightly"))]
130mod non_alias;
131#[cfg(not(feature = "nightly"))]
132pub use non_alias::*;
133
134use core::ops::{Deref, DerefMut};
135
136/// Abstract collection.
137pub trait Collection {
138	/// Type of the items of the collection.
139	type Item;
140}
141
142/// Abstract collection that can be immutably referenced.
143pub trait CollectionRef: Collection {
144	/// Type of references to items of the collection.
145	type ItemRef<'a>: Clone + Deref<Target = Self::Item>
146	where
147		Self: 'a;
148
149	/// Changes an item reference into a shorter lived reference.
150	///
151	/// Item references are [covariant](https://doc.rust-lang.org/nomicon/subtyping.html#variance) with
152	/// regard to the defined lifetime parameter `'a`.
153	/// Since this cannot be directly expressed by the type system, this associated function
154	/// allows one to explicitly shorten the reference's lifetime.
155	///
156	/// You can use the [`covariant_item_ref!`] macro to automatically
157	/// implement this function.
158	fn upcast_item_ref<'short, 'long: 'short>(r: Self::ItemRef<'long>) -> Self::ItemRef<'short>
159	where
160		Self: 'long;
161}
162
163/// Collection where each item reference can be converted into a standard
164/// "simple" rust reference.
165///
166/// This trait is particularly useful to avoid having to include where bounds
167/// of the form `for<'r> T::ItemRef<'r>: Into<&'r T::Item>`, which can
168/// currently lead the compiler to try to prove `T: 'static`
169/// (see https://github.com/rust-lang/rust/pull/96709#issuecomment-1182403490)
170/// for more details.
171pub trait SimpleCollectionRef: CollectionRef {
172	fn into_ref<'r>(r: Self::ItemRef<'r>) -> &'r Self::Item
173	where
174		Self: 'r;
175}
176
177/// Abstract collection that can be mutably referenced.
178pub trait CollectionMut: Collection {
179	/// Type of mutable references to items of the collection.
180	type ItemMut<'a>: DerefMut<Target = Self::Item>
181	where
182		Self: 'a;
183
184	/// Changes an item mutable reference into a shorter lived mutable reference.
185	///
186	/// See the [`CollectionRef::upcast_item_ref`] function for more information.
187	/// You can use the [`covariant_item_mut!`] macro to automatically
188	/// implement this function.
189	fn upcast_item_mut<'short, 'long: 'short>(r: Self::ItemMut<'long>) -> Self::ItemMut<'short>
190	where
191		Self: 'long;
192}
193
194/// Collection where each item reference can be converted into a standard
195/// "simple" rust reference.
196///
197/// This trait is particularly useful to avoid having to include where bounds
198/// of the form `for<'r> T::ItemMut<'r>: Into<&'r mut T::Item>`, which can
199/// currently lead the compiler to try to prove `T: 'static`
200/// (see https://github.com/rust-lang/rust/pull/96709#issuecomment-1182403490)
201/// for more details.
202pub trait SimpleCollectionMut: CollectionMut {
203	fn into_mut<'r>(r: Self::ItemMut<'r>) -> &'r mut Self::Item
204	where
205		Self: 'r;
206}
207
208/// Abstract keyed collection.
209pub trait Keyed: Collection {
210	/// Type of the keys indexing each item of the collection.
211	type Key;
212}
213
214/// Abstract keyed collection whose key can be referenced.
215pub trait KeyedRef: Keyed {
216	/// Type of references to keys of the collection.
217	type KeyRef<'a>: Clone + Deref<Target = Self::Key>
218	where
219		Self: 'a;
220
221	/// Changes a key reference into a shorter lived reference.
222	///
223	/// See the [`CollectionRef::upcast_item_ref`] function for more information.
224	/// You can use the [`covariant_key_ref!`] macro to automatically
225	/// implement this function.
226	fn upcast_key_ref<'short, 'long: 'short>(r: Self::KeyRef<'long>) -> Self::KeyRef<'short>
227	where
228		Self: 'long;
229}
230
231/// Keyed collection where each key reference can be converted into a standard
232/// "simple" rust reference.
233///
234/// This trait is particularly useful to avoid having to include where bounds
235/// of the form `for<'r> T::KeyRef<'r>: Into<&'r T::Key>`, which can
236/// currently lead the compiler to try to prove `T: 'static`
237/// (see https://github.com/rust-lang/rust/pull/96709#issuecomment-1182403490)
238/// for more details.
239pub trait SimpleKeyedRef: KeyedRef {
240	fn into_ref<'r>(r: Self::KeyRef<'r>) -> &'r Self::Key
241	where
242		Self: 'r;
243}
244
245/// Collection that can be created with a minimum given capacity.
246pub trait WithCapacity {
247	/// Creates a new instance of `Self` with the given minimum capacity.
248	fn with_capacity(capacity: usize) -> Self;
249}
250
251/// Sized collection.
252pub trait Len {
253	/// Returns the number of elements in the collection.
254	fn len(&self) -> usize;
255
256	/// Checks if the collection is empty.
257	fn is_empty(&self) -> bool {
258		self.len() == 0
259	}
260}
261
262/// Collection with known capacity.
263pub trait Capacity {
264	/// Returns the current capacity of the collection.
265	///
266	/// This corresponds to the number of elements the collection can hold without reallocation.
267	fn capacity(&self) -> usize;
268}
269
270/// Collection that can extend their capacity.
271pub trait Reserve {
272	/// Reserve enough memory for `edditional` more elements.
273	fn reserve(&mut self, additional: usize);
274}
275
276/// Queryable collection.
277pub trait Get<T>: CollectionRef {
278	/// Returns a reference to the item stored behind the given key (if any).
279	fn get(&self, key: T) -> Option<Self::ItemRef<'_>>;
280
281	/// Checks if the collection contains an item behind the given key.
282	fn contains(&self, key: T) -> bool {
283		self.get(key).is_some()
284	}
285}
286
287/// Mutably queryable collection.
288pub trait GetMut<T>: Get<T> + CollectionMut {
289	/// Returns a mutable reference to the item stored behind the given key (if any).
290	fn get_mut(&mut self, key: T) -> Option<Self::ItemMut<'_>>;
291}
292
293/// Queryable map.
294pub trait GetKeyValue<T>: CollectionRef + KeyedRef {
295	/// Returns the key-value pair matching the given `key`.
296	fn get_key_value(&self, key: T) -> Option<(Self::KeyRef<'_>, Self::ItemRef<'_>)>;
297}
298
299/// Mutably queryable map.
300pub trait GetKeyValueMut<T>: CollectionMut + KeyedRef {
301	/// Returns the key-value pair matching the given `key`, with a mutable reference to the value.
302	fn get_key_value_mut(&mut self, key: T) -> Option<(Self::KeyRef<'_>, Self::ItemMut<'_>)>;
303}
304
305/// Collection exposing a reference to its front element.
306pub trait Front: CollectionRef {
307	/// Get a reference to the front element of the collection.
308	fn front(&self) -> Option<Self::ItemRef<'_>>;
309}
310
311impl<T: Get<usize> + Len> Front for T {
312	fn front(&self) -> Option<Self::ItemRef<'_>> {
313		match self.len() {
314			0 => None,
315			_ => self.get(0),
316		}
317	}
318}
319
320/// Collection exposing a reference to its back element.
321pub trait Back: CollectionRef {
322	/// Get a reference to the back element of the collection.
323	fn back(&self) -> Option<Self::ItemRef<'_>>;
324}
325
326impl<T: Get<usize> + Len> Back for T {
327	fn back(&self) -> Option<Self::ItemRef<'_>> {
328		match self.len() {
329			0 => None,
330			l => self.get(l - 1),
331		}
332	}
333}
334
335/// Collection exposing a mutable reference to its front element.
336pub trait FrontMut: CollectionMut {
337	/// Get a mutable reference to the front element of the collection.
338	fn front_mut(&mut self) -> Option<Self::ItemMut<'_>>;
339}
340
341impl<T: GetMut<usize> + Len> FrontMut for T {
342	fn front_mut(&mut self) -> Option<Self::ItemMut<'_>> {
343		match self.len() {
344			0 => None,
345			_ => self.get_mut(0),
346		}
347	}
348}
349
350/// Collection exposing a mutable reference to its back element.
351pub trait BackMut: CollectionMut {
352	/// Get a mutable reference to the back element of the collection.
353	fn back_mut(&mut self) -> Option<Self::ItemMut<'_>>;
354}
355
356impl<T: GetMut<usize> + Len> BackMut for T {
357	fn back_mut(&mut self) -> Option<Self::ItemMut<'_>> {
358		match self.len() {
359			0 => None,
360			l => self.get_mut(l - 1),
361		}
362	}
363}
364
365/// Mutable collection where new elements can be inserted.
366pub trait Insert: Collection {
367	/// The output of the insertion function.
368	type Output;
369
370	/// Insert a new element in the collection.
371	fn insert(&mut self, element: Self::Item) -> Self::Output;
372}
373
374/// Mutable map where new new key-value pairs can be inserted.
375pub trait MapInsert<K>: Collection {
376	/// The output of the insertion function.
377	type Output;
378
379	/// Insert a new key-value pair in the collection.
380	fn insert(&mut self, key: K, value: Self::Item) -> Self::Output;
381}
382
383/// Mutable collection where new elements can be pushed on the front.
384pub trait PushFront: Collection {
385	/// The output of the push function.
386	type Output;
387
388	/// Push a new element on the front of the collection.
389	fn push_front(&mut self, element: Self::Item) -> Self::Output;
390}
391
392/// Mutable collection where new elements can be pushed on the back.
393pub trait PushBack: Collection {
394	/// The output of the push function.
395	type Output;
396
397	/// Push a new element on the back of the collection.
398	fn push_back(&mut self, element: Self::Item) -> Self::Output;
399}
400
401/// Mutable collection where elements can be removed from.
402pub trait Remove<T>: Collection {
403	/// Remove the element identified by the given `key`.
404	fn remove(&mut self, key: T) -> Option<Self::Item>;
405}
406
407/// Mutable collection where elements can be popped from the front.
408pub trait PopFront: Collection {
409	/// Remove the front element of the collection and return it (if any).
410	fn pop_front(&mut self) -> Option<Self::Item>;
411}
412
413/// Mutable collection where elements can be popped from the back.
414pub trait PopBack: Collection {
415	/// Remove the back element of the collection and return it (if any).
416	fn pop_back(&mut self) -> Option<Self::Item>;
417}
418
419/// Clearable collection.
420pub trait Clear {
421	/// Remove all the elements of the collection.
422	fn clear(&mut self);
423}
424
425/// Iterable collection.
426pub trait Iter: CollectionRef {
427	/// Iterator type.
428	type Iter<'a>: Iterator<Item = Self::ItemRef<'a>>
429	where
430		Self: 'a;
431
432	/// Create an iterator over the items of the collection.
433	fn iter(&self) -> Self::Iter<'_>;
434}
435
436/// Mutably iterable collection.
437pub trait IterMut: CollectionMut {
438	/// Iterator type.
439	type IterMut<'a>: Iterator<Item = Self::ItemMut<'a>>
440	where
441		Self: 'a;
442
443	/// Create an iterator over the mutable items of the collection.
444	fn iter_mut(&mut self) -> Self::IterMut<'_>;
445}
446
447pub trait MapIter: KeyedRef + CollectionRef {
448	type Iter<'a>: Iterator<Item = (Self::KeyRef<'a>, Self::ItemRef<'a>)>
449	where
450		Self: 'a;
451
452	fn iter(&self) -> Self::Iter<'_>;
453}
454
455pub trait MapIterMut: KeyedRef + CollectionMut {
456	type IterMut<'a>: Iterator<Item = (Self::KeyRef<'a>, Self::ItemMut<'a>)>
457	where
458		Self: 'a;
459
460	fn iter_mut(&mut self) -> Self::IterMut<'_>;
461}