stacked_set/
lib.rs

1#![no_std] // <-- see that attr? no shit!
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(any(docsrs, all(feature = "cons", feature = "collection")), doc = include_str!("../README.md"))]
4#![cfg_attr(
5    not(any(docsrs, all(feature = "cons", feature = "collection"))),
6    doc = "(no docs here)"
7)]
8
9use core::borrow::Borrow;
10
11#[cfg(feature = "std-hash")]
12extern crate std;
13
14#[cfg(any(feature = "alloc-vec", feature = "alloc-tree"))]
15extern crate alloc;
16
17/// Defines implementation of [`StackedSet`] based on normal kind of collection.
18#[cfg(feature = "collection")]
19#[cfg_attr(docsrs, doc(cfg(feature = "collection")))]
20pub mod collection;
21
22#[cfg(feature = "cons")]
23#[doc(hidden)]
24mod cons;
25
26#[cfg(feature = "alloc-vec")]
27#[doc(hidden)]
28mod alloc_vec;
29
30#[cfg(feature = "alloc-tree")]
31#[doc(hidden)]
32mod alloc_tree;
33
34#[cfg(feature = "std-hash")]
35#[doc(hidden)]
36mod std_hash;
37
38/// Common trait for stacked set implementations. Users are intended to define their input as `impl StackedSet<Item = WhateverItemTheyNeed>`, so it's up to the user to pick the implementation
39pub trait StackedSet: Sized {
40    /// Item stored in the set
41    type Item;
42
43    /// Creates an empty set
44    #[must_use = "Creating empty set is usually a no-op"]
45    fn empty() -> Self;
46
47    /// Checks if element is present in the set
48    fn contains(&self, item: impl Borrow<Self::Item>) -> bool {
49        self.contains_ref(item.borrow())
50    }
51
52    /// Checks if element is present in the set
53    #[must_use = "Checking for presence does not change set contents"]
54    fn contains_ref(&self, item: &Self::Item) -> bool;
55
56    /// Intended to be the same type, but living for less time
57    type Shorten<'new>: StackedSet<Item = Self::Item> + 'new
58    where
59        Self: 'new;
60
61    /// Adds an item to the stack, returning a new instance now "containing" the item
62    ///
63    /// Note, that original instance is being exclusively borrowed, i.e.
64    /// - new stacked set should not outlive it's parent
65    /// - parent itself cannot be observed while new instance lives
66    ///
67    /// Once this new instance is dropped, original stack is not supposed to contain this new type
68    #[must_use = "Provided value is only contained in a set returned form this call. Despite requiring exclusive borrow, original set is should not be expected to change. Check documentation for more details."]
69    fn extend(&mut self, new_item: Self::Item) -> Self::Shorten<'_>;
70
71    /// Same as [`StackedSet::extend`], but does not actually extend the stackset
72    ///
73    /// Intended to be used, when you need to pass [`StackedSet`] implementor into multiple inner calls, while retaining ownership of the original one
74    #[must_use = "Despite requiring exclusive borrow, original set is should not be expected to change. Check documentation for more details."]
75    fn fork(&mut self) -> Self::Shorten<'_>;
76
77    /// Iterator type for the set
78    type IntoIter<'i>: Iterator<Item = &'i Self::Item> + 'i
79    where
80        Self: 'i;
81
82    /// Returns iterator over the set, no specific order guaranteed
83    fn iter(&self) -> Self::IntoIter<'_>;
84}
85
86#[cfg(feature = "cons")]
87#[cfg_attr(docsrs, doc(cfg(feature = "cons")))]
88pub use cons::ConsSet as StackCons;
89
90#[cfg(feature = "alloc-vec")]
91#[cfg_attr(docsrs, doc(cfg(feature = "alloc-vec")))]
92pub use alloc_vec::Vec as AllocVec;
93
94#[cfg(feature = "alloc-tree")]
95#[cfg_attr(docsrs, doc(cfg(feature = "alloc-tree")))]
96pub use alloc_tree::TreeSet as AllocTree;
97
98#[cfg(feature = "std-hash")]
99#[cfg_attr(docsrs, doc(cfg(feature = "std-hash")))]
100pub use std_hash::Hash as StdHash;
101
102#[cfg(test)]
103mod tests;