gen_map/error.rs
1use core::fmt;
2
3/// Why a [`GenMap`](crate::GenMap) has no room for another value.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum FullError<S> {
6 /// The map has a slot at every index it can use and none of them are
7 /// free. A map uses every index its keys can hold, except the largest
8 /// value of the index type.
9 IndexExhausted,
10
11 /// None of the slots are free and the storage could not make room for
12 /// another one. The field says why, which for a `Vec` is its
13 /// `TryReserveError`.
14 StorageFull(S),
15}
16
17impl<S> FullError<S> {
18 /// Returns the same error with the storage's reason borrowed instead of
19 /// owned.
20 #[inline]
21 pub fn as_ref(&self) -> FullError<&S> {
22 match self {
23 Self::IndexExhausted => FullError::IndexExhausted,
24 Self::StorageFull(error) => FullError::StorageFull(error),
25 }
26 }
27}
28
29impl<S: fmt::Display> fmt::Display for FullError<S> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::IndexExhausted => f.write_str("the keys cannot address another slot"),
33 Self::StorageFull(error) => {
34 write!(f, "the storage cannot make room for another slot: {error}")
35 }
36 }
37 }
38}
39
40/// Why [`GenMap::try_insert`](crate::GenMap::try_insert) could not insert.
41/// Each variant hands the value back so that the caller can keep it. `S` is
42/// the map's [`StorageError`](crate::StorageError).
43///
44/// When the keys have no index left for a new slot and the storage is also
45/// full, the error is [`IndexExhausted`](Self::IndexExhausted).
46pub enum InsertError<T, S> {
47 /// The map has a slot at every index it can use and none of them are
48 /// free. A map uses every index its keys can hold, except the largest
49 /// value of the index type.
50 IndexExhausted(T),
51
52 /// None of the slots are free and the storage could not make room for
53 /// another one. The second field says why.
54 StorageFull(T, S),
55}
56
57impl<T, S> InsertError<T, S> {
58 /// Takes the value back out of the error.
59 #[inline]
60 pub fn into_inner(self) -> T {
61 match self {
62 Self::IndexExhausted(value) | Self::StorageFull(value, _) => value,
63 }
64 }
65
66 /// The reason the insert failed, without the value.
67 #[inline]
68 pub fn kind(&self) -> FullError<&S> {
69 match self {
70 Self::IndexExhausted(_) => FullError::IndexExhausted,
71 Self::StorageFull(_, error) => FullError::StorageFull(error),
72 }
73 }
74
75 /// Splits the error into its reason and the value.
76 #[inline]
77 pub fn into_parts(self) -> (FullError<S>, T) {
78 match self {
79 Self::IndexExhausted(value) => (FullError::IndexExhausted, value),
80 Self::StorageFull(value, error) => (FullError::StorageFull(error), value),
81 }
82 }
83}
84
85// This impl is written by hand so that it does not require `T: Debug`.
86impl<T, S: fmt::Debug> fmt::Debug for InsertError<T, S> {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 match self {
89 Self::IndexExhausted(_) => f.write_str("IndexExhausted(..)"),
90 Self::StorageFull(_, error) => write!(f, "StorageFull(.., {error:?})"),
91 }
92 }
93}
94
95impl<T, S: fmt::Display> fmt::Display for InsertError<T, S> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 fmt::Display::fmt(&self.kind(), f)
98 }
99}
100
101/// Why [`SecondaryMap::insert`](crate::SecondaryMap::insert) could not
102/// insert. Each variant hands the value back so that the caller can keep it.
103/// `S` is the map's [`SecondaryStorageError`](crate::SecondaryStorageError).
104pub enum SecondaryInsertError<T, S> {
105 /// The slot at the key's index holds a value that was inserted under a
106 /// different generation, and the config's
107 /// [`ReplaceStrategy`](crate::ReplaceStrategy) kept that value.
108 Refused(T),
109
110 /// The key's index is the largest value of the index type. No map gives
111 /// a slot that index, so only a hand-built key can have it.
112 IndexReserved(T),
113
114 /// The storage could not make room for a slot at the key's index. The
115 /// second field says why.
116 StorageFull(T, S),
117}
118
119impl<T, S> SecondaryInsertError<T, S> {
120 /// Takes the value back out of the error.
121 #[inline]
122 pub fn into_inner(self) -> T {
123 match self {
124 Self::Refused(value) | Self::IndexReserved(value) | Self::StorageFull(value, _) => {
125 value
126 }
127 }
128 }
129}
130
131// This impl is written by hand so that it does not require `T: Debug`.
132impl<T, S: fmt::Debug> fmt::Debug for SecondaryInsertError<T, S> {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 match self {
135 Self::Refused(_) => f.write_str("Refused(..)"),
136 Self::IndexReserved(_) => f.write_str("IndexReserved(..)"),
137 Self::StorageFull(_, error) => write!(f, "StorageFull(.., {error:?})"),
138 }
139 }
140}
141
142impl<T, S: fmt::Display> fmt::Display for SecondaryInsertError<T, S> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 match self {
145 Self::Refused(_) => f.write_str(
146 "the slot holds a value from a different generation, and the replace strategy kept it",
147 ),
148 Self::IndexReserved(_) => f.write_str(
149 "the key's index is the largest value of the index type, which no slot ever has",
150 ),
151 Self::StorageFull(_, error) => {
152 write!(f, "the storage cannot make room for the slot: {error}")
153 }
154 }
155 }
156}
157
158/// Why [`GenMap::try_insert_with_key`](crate::GenMap::try_insert_with_key)
159/// could not insert. The map can be full before the closure runs, or the
160/// closure can refuse to make a value, and the variant says which of the two
161/// happened. `E` is the closure's error and `S` is the map's
162/// [`StorageError`](crate::StorageError).
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
164pub enum InsertWithError<E, S> {
165 /// The map had no room, so the closure was never called.
166 Full(FullError<S>),
167
168 /// The closure returned this error, so nothing was inserted.
169 Rejected(E),
170}
171
172impl<E, S> InsertWithError<E, S> {
173 /// Converts the error into `E`, using `E`'s `From<FullError<S>>` impl
174 /// for a full map, so that a caller with its own error type gets that
175 /// type back.
176 ///
177 /// # Examples
178 ///
179 /// ```
180 /// use gen_map::{FullError, GenMap};
181 /// use std::collections::TryReserveError;
182 ///
183 /// #[derive(Debug)]
184 /// enum MyError {
185 /// Full(FullError<TryReserveError>),
186 /// Parse,
187 /// }
188 ///
189 /// impl From<FullError<TryReserveError>> for MyError {
190 /// fn from(e: FullError<TryReserveError>) -> Self {
191 /// MyError::Full(e)
192 /// }
193 /// }
194 ///
195 /// fn add(map: &mut GenMap<u32>, text: &str) -> Result<(), MyError> {
196 /// map.try_insert_with_key(|_| text.parse().map_err(|_| MyError::Parse))
197 /// .map_err(|e| e.flatten())?;
198 /// Ok(())
199 /// }
200 ///
201 /// let mut map = GenMap::new();
202 /// assert!(add(&mut map, "7").is_ok());
203 /// assert!(matches!(add(&mut map, "x"), Err(MyError::Parse)));
204 /// ```
205 #[inline]
206 pub fn flatten(self) -> E
207 where
208 E: From<FullError<S>>,
209 {
210 match self {
211 Self::Full(full) => E::from(full),
212 Self::Rejected(error) => error,
213 }
214 }
215
216 /// Returns the closure's error, or `None` if the map was full.
217 #[inline]
218 pub fn rejected(self) -> Option<E> {
219 match self {
220 Self::Rejected(error) => Some(error),
221 Self::Full(_) => None,
222 }
223 }
224
225 /// Returns `true` if the map was full.
226 #[inline]
227 pub fn is_full(&self) -> bool {
228 matches!(self, Self::Full(_))
229 }
230}
231
232impl<E, S> From<FullError<S>> for InsertWithError<E, S> {
233 #[inline]
234 fn from(full: FullError<S>) -> Self {
235 Self::Full(full)
236 }
237}
238
239impl<E: fmt::Display, S: fmt::Display> fmt::Display for InsertWithError<E, S> {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 match self {
242 Self::Full(full) => fmt::Display::fmt(full, f),
243 Self::Rejected(error) => fmt::Display::fmt(error, f),
244 }
245 }
246}
247
248/// Why [`GenMap::get_disjoint_mut`](crate::GenMap::get_disjoint_mut) or
249/// [`SecondaryMap::get_disjoint_mut`](crate::SecondaryMap::get_disjoint_mut)
250/// could not hand out its references.
251#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
252pub enum GetDisjointMutError {
253 /// The map has no value for one of the keys, meaning the map's
254 /// `contains_key` returns `false` for it.
255 InvalidKey,
256
257 /// Two or more of the keys point at the same slot, so the references would
258 /// alias.
259 OverlappingKeys,
260}
261
262impl fmt::Display for GetDisjointMutError {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 match self {
265 Self::InvalidKey => f.write_str("one of the keys is invalid"),
266 Self::OverlappingKeys => f.write_str("two of the keys point at the same slot"),
267 }
268 }
269}
270
271/// Why [`GenMap::get_disjoint_mut_at`](crate::GenMap::get_disjoint_mut_at) or
272/// [`SecondaryMap::get_disjoint_mut_at`](crate::SecondaryMap::get_disjoint_mut_at)
273/// could not hand out its references.
274#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
275pub enum GetDisjointMutAtError {
276 /// There is no slot at one of the indices, or the slot holds no value,
277 /// meaning the map's `key_at` returns `None` for it.
278 NoValue,
279
280 /// Two of the indices are the same, so the references would alias.
281 OverlappingIndices,
282}
283
284impl fmt::Display for GetDisjointMutAtError {
285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286 match self {
287 Self::NoValue => f.write_str("one of the indices has no value"),
288 Self::OverlappingIndices => f.write_str("two of the indices are the same"),
289 }
290 }
291}