frozen_collections_core/fz_sets/
fz_string_set.rs

1use crate::DefaultHashBuilder;
2use crate::fz_maps::FzStringMap;
3use crate::hashers::{LeftRangeHasher, RightRangeHasher};
4use crate::sets::decl_macros::{
5    bitand_fn, bitor_fn, bitxor_fn, debug_fn, into_iter_fn, into_iter_ref_fn, partial_eq_fn,
6    set_iteration_funcs, sub_fn,
7};
8use crate::sets::{IntoIter, Iter};
9use crate::traits::{Hasher, Len, MapIteration, MapQuery, Set, SetIteration, SetOps, SetQuery};
10use alloc::vec::Vec;
11use core::fmt::Debug;
12use core::hash::BuildHasher;
13use core::hash::Hash;
14use core::iter::FromIterator;
15use core::ops::{BitAnd, BitOr, BitXor, Sub};
16use equivalent::Equivalent;
17use foldhash::fast::RandomState;
18#[cfg(feature = "serde")]
19use {
20    crate::sets::decl_macros::serialize_fn,
21    core::fmt::Formatter,
22    core::marker::PhantomData,
23    serde::de::{SeqAccess, Visitor},
24    serde::ser::SerializeSeq,
25    serde::{Deserialize, Deserializer, Serialize, Serializer},
26};
27
28/// A set optimized for fast read access with string values.
29///
30#[doc = include_str!("../doc_snippets/about.md")]
31#[doc = include_str!("../doc_snippets/hash_warning.md")]
32///
33/// # Alternate Choices
34///
35/// If your values are known at compile time, consider using the various `fz_*_set` macros instead of
36/// this type as they generally perform better.
37#[derive(Clone)]
38pub struct FzStringSet<T, BH = DefaultHashBuilder> {
39    map: FzStringMap<T, (), BH>,
40}
41
42impl<'a> FzStringSet<&'a str, DefaultHashBuilder> {
43    /// Creates a new frozen set.
44    #[must_use]
45    pub fn new(entries: Vec<&'a str>) -> Self {
46        Self::with_hasher(entries, RandomState::default())
47    }
48}
49
50impl<'a, BH> FzStringSet<&'a str, BH>
51where
52    BH: BuildHasher,
53{
54    /// Creates a new frozen set which uses the given hash builder to hash values.
55    #[must_use]
56    pub fn with_hasher(entries: Vec<&'a str>, bh: BH) -> Self {
57        Self {
58            map: FzStringMap::with_hasher(entries.into_iter().map(|x| (x, ())).collect(), bh),
59        }
60    }
61}
62
63impl<BH> Default for FzStringSet<&str, BH>
64where
65    BH: Default,
66{
67    fn default() -> Self {
68        Self {
69            map: FzStringMap::default(),
70        }
71    }
72}
73
74impl<'a, BH> From<FzStringMap<&'a str, (), BH>> for FzStringSet<&'a str, BH> {
75    fn from(map: FzStringMap<&'a str, (), BH>) -> Self {
76        Self { map }
77    }
78}
79
80impl<'a, const N: usize, BH> From<[&'a str; N]> for FzStringSet<&'a str, BH>
81where
82    BH: BuildHasher + Default,
83{
84    fn from(entries: [&'a str; N]) -> Self {
85        Self::from(FzStringMap::from_iter(entries.into_iter().map(|x| (x, ()))))
86    }
87}
88
89impl<'a, BH> FromIterator<&'a str> for FzStringSet<&'a str, BH>
90where
91    BH: BuildHasher + Default,
92{
93    fn from_iter<IT: IntoIterator<Item = &'a str>>(iter: IT) -> Self {
94        Self::from(FzStringMap::from_iter(iter.into_iter().map(|x| (x, ()))))
95    }
96}
97
98impl<T, Q, BH> Set<T, Q> for FzStringSet<T, BH>
99where
100    Q: ?Sized + Hash + Eq + Len + Equivalent<T>,
101    BH: BuildHasher,
102    LeftRangeHasher<BH>: Hasher<Q>,
103    RightRangeHasher<BH>: Hasher<Q>,
104{
105}
106
107impl<T, Q, BH> SetQuery<T, Q> for FzStringSet<T, BH>
108where
109    Q: ?Sized + Hash + Eq + Len + Equivalent<T>,
110    BH: BuildHasher,
111    LeftRangeHasher<BH>: Hasher<Q>,
112    RightRangeHasher<BH>: Hasher<Q>,
113{
114    #[inline]
115    fn get(&self, value: &Q) -> Option<&T> {
116        Some(self.map.get_key_value(value)?.0)
117    }
118}
119
120impl<T, BH> SetIteration<T> for FzStringSet<T, BH> {
121    type Iterator<'a>
122        = Iter<'a, T>
123    where
124        T: 'a,
125        BH: 'a;
126
127    set_iteration_funcs!();
128}
129
130impl<T, BH> Len for FzStringSet<T, BH> {
131    fn len(&self) -> usize {
132        self.map.len()
133    }
134}
135
136impl<T, ST, BH> BitOr<&ST> for &FzStringSet<T, BH>
137where
138    T: Hash + Eq + Len + Clone,
139    ST: Set<T>,
140    BH: BuildHasher + Default,
141    LeftRangeHasher<BH>: Hasher<T>,
142    RightRangeHasher<BH>: Hasher<T>,
143{
144    bitor_fn!();
145}
146
147impl<T, ST, BH> BitAnd<&ST> for &FzStringSet<T, BH>
148where
149    T: Hash + Eq + Len + Clone,
150    ST: Set<T>,
151    BH: BuildHasher + Default,
152    LeftRangeHasher<BH>: Hasher<T>,
153    RightRangeHasher<BH>: Hasher<T>,
154{
155    bitand_fn!();
156}
157
158impl<T, ST, BH> BitXor<&ST> for &FzStringSet<T, BH>
159where
160    T: Hash + Eq + Len + Clone,
161    ST: Set<T>,
162    BH: BuildHasher + Default,
163    LeftRangeHasher<BH>: Hasher<T>,
164    RightRangeHasher<BH>: Hasher<T>,
165{
166    bitxor_fn!();
167}
168
169impl<T, ST, BH> Sub<&ST> for &FzStringSet<T, BH>
170where
171    T: Hash + Eq + Len + Clone,
172    ST: Set<T>,
173    BH: BuildHasher + Default,
174    LeftRangeHasher<BH>: Hasher<T>,
175    RightRangeHasher<BH>: Hasher<T>,
176{
177    sub_fn!();
178}
179
180impl<T, BH> IntoIterator for FzStringSet<T, BH> {
181    into_iter_fn!();
182}
183
184impl<'a, T, BH> IntoIterator for &'a FzStringSet<T, BH> {
185    into_iter_ref_fn!();
186}
187
188impl<T, ST, BH> PartialEq<ST> for FzStringSet<T, BH>
189where
190    T: Hash + Eq + Len,
191    ST: Set<T>,
192    BH: BuildHasher + Default,
193    LeftRangeHasher<BH>: Hasher<T>,
194    RightRangeHasher<BH>: Hasher<T>,
195{
196    partial_eq_fn!();
197}
198
199impl<T, BH> Eq for FzStringSet<T, BH>
200where
201    T: Hash + Eq + Len,
202    BH: BuildHasher + Default,
203    LeftRangeHasher<BH>: Hasher<T>,
204    RightRangeHasher<BH>: Hasher<T>,
205{
206}
207
208impl<T, BH> Debug for FzStringSet<T, BH>
209where
210    T: Debug,
211{
212    debug_fn!();
213}
214
215#[cfg(feature = "serde")]
216impl<T> Serialize for FzStringSet<T>
217where
218    T: Serialize,
219{
220    serialize_fn!();
221}
222
223#[cfg(feature = "serde")]
224impl<'de, BH> Deserialize<'de> for FzStringSet<&'de str, BH>
225where
226    BH: BuildHasher + Default,
227{
228    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
229    where
230        D: Deserializer<'de>,
231    {
232        deserializer.deserialize_seq(SetVisitor {
233            marker: PhantomData,
234        })
235    }
236}
237
238#[cfg(feature = "serde")]
239struct SetVisitor<BH> {
240    marker: PhantomData<BH>,
241}
242
243#[cfg(feature = "serde")]
244impl<'de, BH> Visitor<'de> for SetVisitor<BH>
245where
246    BH: BuildHasher + Default,
247{
248    type Value = FzStringSet<&'de str, BH>;
249
250    fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result {
251        formatter.write_str("a set with string values")
252    }
253
254    fn visit_seq<M>(self, mut access: M) -> core::result::Result<Self::Value, M::Error>
255    where
256        M: SeqAccess<'de>,
257    {
258        let mut v = Vec::with_capacity(access.size_hint().unwrap_or(0));
259        while let Some(x) = access.next_element()? {
260            v.push((x, ()));
261        }
262
263        Ok(FzStringSet::from(FzStringMap::with_hasher(
264            v,
265            BH::default(),
266        )))
267    }
268}