Skip to main content

wasmtime_environ/collections/
index_set.rs

1use crate::{
2    collections::{TryClone, TryFromIterator},
3    error::OutOfMemory,
4};
5use core::{
6    borrow::Borrow,
7    fmt,
8    hash::{BuildHasher, Hash},
9    marker::PhantomData,
10    mem,
11    ops::Index,
12};
13use indexmap::set as inner;
14
15#[cfg(feature = "std")]
16use std::hash::RandomState as DefaultHashBuilder;
17
18#[cfg(not(feature = "std"))]
19use hashbrown::DefaultHashBuilder;
20
21/// A wrapper around [`indexmap::IndexSet`] that only provides fallible
22/// allocation.
23pub struct TryIndexSet<T, S = DefaultHashBuilder> {
24    inner: indexmap::IndexSet<T, S>,
25}
26
27impl<T, S> Default for TryIndexSet<T, S>
28where
29    S: Default,
30{
31    fn default() -> Self {
32        Self {
33            inner: indexmap::IndexSet::default(),
34        }
35    }
36}
37
38impl<T, S> PartialEq for TryIndexSet<T, S>
39where
40    T: Eq + Hash,
41    S: BuildHasher,
42{
43    fn eq(&self, other: &Self) -> bool {
44        self.inner.eq(&other.inner)
45    }
46}
47
48impl<T, S> Eq for TryIndexSet<T, S>
49where
50    T: Eq + Hash,
51    S: BuildHasher,
52{
53}
54
55impl<T, S> TryClone for TryIndexSet<T, S>
56where
57    T: Eq + Hash + TryClone,
58    S: BuildHasher + TryClone,
59{
60    fn try_clone(&self) -> Result<Self, OutOfMemory> {
61        let mut set = Self::with_hasher(self.inner.hasher().try_clone()?);
62        set.reserve(self.len())?;
63        for value in self.iter() {
64            set.insert(value.try_clone()?)?;
65        }
66        Ok(set)
67    }
68}
69
70impl<T, S> fmt::Debug for TryIndexSet<T, S>
71where
72    T: fmt::Debug,
73{
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        fmt::Debug::fmt(&self.inner, f)
76    }
77}
78
79impl<T, S> From<TryIndexSet<T, S>> for indexmap::IndexSet<T, S> {
80    fn from(set: TryIndexSet<T, S>) -> Self {
81        set.inner
82    }
83}
84
85impl<T, S> From<indexmap::IndexSet<T, S>> for TryIndexSet<T, S> {
86    fn from(inner: indexmap::IndexSet<T, S>) -> Self {
87        Self { inner }
88    }
89}
90
91impl<T, S> serde::ser::Serialize for TryIndexSet<T, S>
92where
93    T: serde::ser::Serialize,
94{
95    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
96    where
97        Ser: serde::Serializer,
98    {
99        use serde::ser::SerializeSeq as _;
100        let mut seq = serializer.serialize_seq(Some(self.len()))?;
101        for value in self {
102            seq.serialize_element(value)?;
103        }
104        seq.end()
105    }
106}
107
108impl<'de, T> serde::de::Deserialize<'de> for TryIndexSet<T>
109where
110    T: serde::de::Deserialize<'de> + Hash + Eq,
111{
112    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
113    where
114        D: serde::Deserializer<'de>,
115    {
116        struct Visitor<T>(PhantomData<fn() -> TryIndexSet<T>>);
117
118        impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
119        where
120            T: serde::de::Deserialize<'de> + Hash + Eq,
121        {
122            type Value = TryIndexSet<T>;
123
124            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
125                f.write_str("an `IndexSet`")
126            }
127
128            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
129            where
130                A: serde::de::SeqAccess<'de>,
131            {
132                use serde::de::Error as _;
133
134                let mut result = TryIndexSet::<T>::new();
135
136                if let Some(len) = seq.size_hint() {
137                    result.reserve(len).map_err(|oom| A::Error::custom(oom))?;
138                }
139
140                while let Some(value) = seq.next_element::<T>()? {
141                    result.insert(value).map_err(|oom| A::Error::custom(oom))?;
142                }
143
144                Ok(result)
145            }
146        }
147
148        deserializer.deserialize_seq(Visitor(PhantomData))
149    }
150}
151
152impl<T> TryFromIterator<T, OutOfMemory> for TryIndexSet<T>
153where
154    T: Hash + Eq,
155{
156    fn try_from_iter<I>(iter: I) -> Result<Self, OutOfMemory>
157    where
158        I: Iterator<Item = T>,
159    {
160        let mut set = Self::new();
161        set.reserve(iter.size_hint().0)?;
162        for value in iter {
163            set.insert(value)?;
164        }
165        Ok(set)
166    }
167}
168
169impl<T, E> TryFromIterator<Result<T, E>, E> for TryIndexSet<T>
170where
171    T: Hash + Eq,
172    E: From<OutOfMemory>,
173{
174    fn try_from_iter<I>(iter: I) -> Result<Self, E>
175    where
176        I: Iterator<Item = Result<T, E>>,
177    {
178        let mut set = Self::new();
179        set.reserve(iter.size_hint().0)?;
180        for value in iter {
181            set.insert(value?)?;
182        }
183        Ok(set)
184    }
185}
186
187impl<T> TryIndexSet<T> {
188    /// Same as [`indexmap::IndexSet::new`].
189    pub fn new() -> Self {
190        Self {
191            inner: indexmap::IndexSet::with_hasher(Default::default()),
192        }
193    }
194}
195
196impl<T, S> TryIndexSet<T, S> {
197    /// Same as [`indexmap::IndexSet::with_hasher`].
198    pub const fn with_hasher(hash_builder: S) -> Self {
199        TryIndexSet {
200            inner: indexmap::IndexSet::with_hasher(hash_builder),
201        }
202    }
203
204    /// Same as [`indexmap::IndexSet::len`].
205    pub fn len(&self) -> usize {
206        self.inner.len()
207    }
208
209    /// Same as [`indexmap::IndexSet::is_empty`].
210    pub fn is_empty(&self) -> bool {
211        self.inner.is_empty()
212    }
213
214    /// Same as [`indexmap::IndexSet::iter`].
215    pub fn iter(&self) -> inner::Iter<'_, T> {
216        self.inner.iter()
217    }
218
219    /// Same as [`indexmap::IndexSet::get_index`].
220    pub fn get_index(&self, index: usize) -> Option<&T> {
221        self.inner.get_index(index)
222    }
223
224    /// Same as [`indexmap::IndexSet::reserve`] but returns an error on
225    /// allocation failure.
226    pub fn reserve(&mut self, additional: usize) -> Result<(), OutOfMemory> {
227        self.inner.try_reserve(additional).map_err(|_| {
228            let new_len = self.len().saturating_add(additional);
229            OutOfMemory::new(new_len.saturating_mul(mem::size_of::<T>()))
230        })
231    }
232}
233
234impl<T, S> TryIndexSet<T, S>
235where
236    T: Hash + Eq,
237    S: BuildHasher,
238{
239    /// Same as [`indexmap::IndexSet::insert`] but returns an error on
240    /// allocation failure.
241    pub fn insert(&mut self, value: T) -> Result<bool, OutOfMemory> {
242        self.reserve(1)?;
243        Ok(self.inner.insert(value))
244    }
245
246    /// Same as [`indexmap::IndexSet::contains`].
247    pub fn contains<Q>(&self, value: &Q) -> bool
248    where
249        Q: ?Sized + Hash + Eq,
250        T: Borrow<Q>,
251    {
252        self.inner.contains(value)
253    }
254
255    /// Same as [`indexmap::IndexSet::get_index_of`].
256    pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
257    where
258        Q: ?Sized + Hash + Eq,
259        T: Borrow<Q>,
260    {
261        self.inner.get_index_of(value)
262    }
263}
264
265impl<T, S> Index<usize> for TryIndexSet<T, S> {
266    type Output = T;
267
268    fn index(&self, index: usize) -> &T {
269        &self.inner[index]
270    }
271}
272
273impl<'a, T, S> IntoIterator for &'a TryIndexSet<T, S> {
274    type Item = &'a T;
275    type IntoIter = inner::Iter<'a, T>;
276
277    fn into_iter(self) -> Self::IntoIter {
278        self.iter()
279    }
280}
281
282impl<T, S> IntoIterator for TryIndexSet<T, S> {
283    type Item = T;
284    type IntoIter = inner::IntoIter<T>;
285
286    fn into_iter(self) -> Self::IntoIter {
287        self.inner.into_iter()
288    }
289}