either_or_both/either_or_both/traits.rs
1//! Trait implementations for `EitherOrBoth`
2
3#[cfg(any(
4 feature = "std",
5 feature = "indexmap",
6 all(feature = "std", feature = "either"),
7 all(feature = "indexmap", feature = "either")
8))]
9macro_rules! collect {
10 (
11 $iter:expr;
12 $cap:ident =>
13 $new_left:expr,
14 $new_right:expr; fold => |
15 ($left:ident, $right:ident),
16 $either:ident |
17 $body:expr
18 ) => {{
19 let into_iter = $iter.into_iter();
20 let $cap = match into_iter.size_hint() {
21 (_, Some(upper)) => upper,
22 (lower, None) => lower,
23 };
24
25 let (left, right) = into_iter.fold(
26 ($new_left, $new_right),
27 |(mut $left, mut $right), $either| $body,
28 );
29
30 match (left.is_empty(), right.is_empty()) {
31 (true, true) | (false, false) => Self::Both(left, right),
32 (true, false) => Self::Right(right),
33 (false, true) => Self::Left(left),
34 }
35 }};
36}
37
38use core::cmp::Ordering;
39use core::fmt::Display;
40#[cfg(feature = "std")]
41use std::{
42 collections::{HashMap, HashSet},
43 error::Error,
44 vec::Vec,
45};
46
47#[cfg(feature = "indexmap")]
48use indexmap::{IndexMap, IndexSet};
49
50use crate::iter::{IntoIterEitherOrBoth, IterEitherOrBoth, IterMutEitherOrBoth};
51#[cfg(feature = "either")]
52use crate::Either;
53use crate::{EitherOrBoth, TryFromOptionsError};
54
55impl<T> IntoIterator for EitherOrBoth<T, T> {
56 type Item = T;
57 type IntoIter = IntoIterEitherOrBoth<T>;
58
59 /// Returns a consuming iterator over the contained values of a uniform type
60 ///
61 /// The evaluation order is from left to right if this is a [`Both`] variant. To
62 /// reverse the order use [`flip`].
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// use either_or_both::EitherOrBoth;
68 ///
69 /// let value: EitherOrBoth<char> = EitherOrBoth::Both('c', 'a');
70 /// let mut iter = value.into_iter();
71 /// assert_eq!(iter.next(), Some('c'));
72 /// assert_eq!(iter.next(), Some('a'));
73 /// assert_eq!(iter.next(), None);
74 ///
75 /// let value: EitherOrBoth<char> = EitherOrBoth::Left('c');
76 /// let mut iter = value.into_iter();
77 /// assert_eq!(iter.next(), Some('c'));
78 /// assert_eq!(iter.next(), None);
79 /// ```
80 ///
81 /// [`Both`]: EitherOrBoth::Both
82 /// [`flip`]: EitherOrBoth::flip
83 fn into_iter(self) -> Self::IntoIter {
84 IntoIterEitherOrBoth::new(self)
85 }
86}
87
88impl<'a, T> IntoIterator for &'a EitherOrBoth<T, T> {
89 type Item = &'a T;
90 type IntoIter = IterEitherOrBoth<'a, T>;
91
92 fn into_iter(self) -> Self::IntoIter {
93 IterEitherOrBoth::new(self)
94 }
95}
96
97impl<'a, T> IntoIterator for &'a mut EitherOrBoth<T, T> {
98 type Item = &'a mut T;
99 type IntoIter = IterMutEitherOrBoth<'a, T>;
100
101 fn into_iter(self) -> Self::IntoIter {
102 IterMutEitherOrBoth::new(self)
103 }
104}
105
106////////////////////////////////////////////////////////////////////////////////
107// FromIterator implementations for EitherOrBoth
108////////////////////////////////////////////////////////////////////////////////
109
110#[cfg(feature = "std")]
111impl<L, R> FromIterator<EitherOrBoth<L, R>> for EitherOrBoth<Vec<L>, Vec<R>> {
112 /// Consumes an [`Iterator`] of [`EitherOrBoth`] items, collecting all left and right
113 /// values into separate [vectors].
114 ///
115 /// - If only left values are present, returns [`Left`] with the left [`Vec`].
116 /// - If only right values are present, returns [`Right`] with the right [`Vec`].
117 /// - If none or both left and right values are present, returns [`Both`] with both
118 /// [`Vec`]s.
119 ///
120 /// # Examples
121 ///
122 /// This example collects into a [`Both`] variant:
123 #[cfg_attr(feature = "std", doc = "```rust")]
124 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
125 /// use either_or_both::EitherOrBoth;
126 ///
127 /// let items: Vec<EitherOrBoth<u8, char>> =
128 /// vec![EitherOrBoth::Both(1, 'c'), EitherOrBoth::Left(2)];
129 ///
130 /// let collected: EitherOrBoth<Vec<u8>, Vec<char>> = items.into_iter().collect();
131 ///
132 /// assert_eq!(collected, EitherOrBoth::Both(vec![1, 2], vec!['c']));
133 /// ```
134 ///
135 /// This example collects into a [`Left`] variant:
136 #[cfg_attr(feature = "std", doc = "```rust")]
137 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
138 /// use either_or_both::EitherOrBoth;
139 ///
140 /// let items: Vec<EitherOrBoth<u8, char>> = vec![EitherOrBoth::Left(2)];
141 /// let collected: EitherOrBoth<Vec<u8>, Vec<char>> = items.into_iter().collect();
142 ///
143 /// assert_eq!(collected, EitherOrBoth::Left(vec![2]));
144 /// ```
145 ///
146 /// [vectors]: Vec
147 /// [`Left`]: EitherOrBoth::Left
148 /// [`Right`]: EitherOrBoth::Right
149 /// [`Both`]: EitherOrBoth::Both
150 fn from_iter<T: IntoIterator<Item = EitherOrBoth<L, R>>>(iter: T) -> Self {
151 collect!(
152 iter;
153 cap => Vec::with_capacity(cap), Vec::with_capacity(cap);
154 fold => |(left, right), either| {
155 either.biapply(|l| left.push(l), |r| right.push(r));
156 (left, right)
157 })
158 }
159}
160
161#[cfg(feature = "std")]
162impl<K1, K2, V1, V2, S1, S2> FromIterator<EitherOrBoth<(K1, V1), (K2, V2)>>
163 for EitherOrBoth<HashMap<K1, V1, S1>, HashMap<K2, V2, S2>>
164where
165 K1: core::hash::Hash + Eq,
166 K2: core::hash::Hash + Eq,
167 S1: core::hash::BuildHasher + Default,
168 S2: core::hash::BuildHasher + Default,
169{
170 /// Consumes an [`Iterator`] of [`EitherOrBoth`] items, collecting all left and right
171 /// values into separate [`HashMaps`].
172 ///
173 /// - If only left values are present, returns [`Left`] with the left [`HashMap`].
174 /// - If only right values are present, returns [`Right`] with the right [`HashMap`].
175 /// - If none or both left and right values are present, returns [`Both`] with both
176 /// [`HashMaps`].
177 ///
178 /// # Examples
179 ///
180 /// This example collects into a [`Both`] variant:
181 #[cfg_attr(feature = "std", doc = "```rust")]
182 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
183 /// use std::collections::HashMap;
184 ///
185 /// use either_or_both::EitherOrBoth;
186 ///
187 /// let items: Vec<EitherOrBoth<(&str, u8), (&str, char)>> = vec![
188 /// EitherOrBoth::Both(("both_l", 1), ("both_r", 'c')),
189 /// EitherOrBoth::Left(("left", 2)),
190 /// ];
191 ///
192 /// let collected: EitherOrBoth<HashMap<&str, u8>, HashMap<&str, char>> =
193 /// items.into_iter().collect();
194 ///
195 /// assert_eq!(
196 /// collected,
197 /// EitherOrBoth::Both(
198 /// HashMap::from([("both_l", 1), ("left", 2)]),
199 /// HashMap::from([("both_r", 'c')])
200 /// )
201 /// );
202 /// ```
203 ///
204 /// This example collects into a [`Left`] variant:
205 #[cfg_attr(feature = "std", doc = "```rust")]
206 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
207 /// use std::collections::HashMap;
208 ///
209 /// use either_or_both::EitherOrBoth;
210 ///
211 /// let items: Vec<EitherOrBoth<(&str, u8), (&str, char)>> =
212 /// vec![EitherOrBoth::Left(("left", 2))];
213 ///
214 /// let collected: EitherOrBoth<HashMap<&str, u8>, HashMap<&str, char>> =
215 /// items.into_iter(). collect();
216 ///
217 /// assert_eq!(collected, EitherOrBoth::Left(HashMap::from([("left", 2)]),));
218 /// ```
219 ///
220 /// [`HashMaps`]: std::collections::HashMap
221 /// [`Left`]: EitherOrBoth::Left
222 /// [`Right`]: EitherOrBoth::Right
223 /// [`Both`]: EitherOrBoth::Both
224 fn from_iter<T>(iter: T) -> Self
225 where
226 T: IntoIterator<Item = EitherOrBoth<(K1, V1), (K2, V2)>>,
227 {
228 collect!(
229 iter;
230 cap => HashMap::with_capacity_and_hasher(cap, S1::default()),
231 HashMap::with_capacity_and_hasher(cap, S2::default());
232 fold => |(left, right), either| {
233 either.biapply(
234 |(k1, v1)| {
235 left.insert(k1, v1);
236 },
237 |(k2, v2)| {
238 right.insert(k2, v2);
239 },
240 );
241 (left, right)
242 })
243 }
244}
245
246#[cfg(feature = "std")]
247impl<K1, K2, S1, S2> FromIterator<EitherOrBoth<K1, K2>>
248 for EitherOrBoth<HashSet<K1, S1>, HashSet<K2, S2>>
249where
250 K1: core::hash::Hash + Eq,
251 K2: core::hash::Hash + Eq,
252 S1: core::hash::BuildHasher + Default,
253 S2: core::hash::BuildHasher + Default,
254{
255 /// Consumes an [`Iterator`] of [`EitherOrBoth`] items, collecting all left and right
256 /// values into separate [`HashSets`].
257 ///
258 /// - If only left values are present, returns [`Left`] with the left [`HashSet`].
259 /// - If only right values are present, returns [`Right`] with the right [`HashSet`].
260 /// - If none or both left and right values are present, returns [`Both`] with both
261 /// [`HashSets`].
262 ///
263 /// # Examples
264 ///
265 /// This example collects into a [`Both`] variant:
266 #[cfg_attr(feature = "std", doc = "```rust")]
267 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
268 /// use std::collections::HashSet;
269 ///
270 /// use either_or_both::EitherOrBoth;
271 ///
272 /// let items: Vec<EitherOrBoth<u8, char>> =
273 /// vec![EitherOrBoth::Both(1, 'c'), EitherOrBoth::Left(2)];
274 ///
275 /// let collected: EitherOrBoth<HashSet<u8>, HashSet<char>> =
276 /// items.into_iter().collect();
277 ///
278 /// assert_eq!(
279 /// collected,
280 /// EitherOrBoth::Both(HashSet::from([1, 2]), HashSet::from(['c']))
281 /// );
282 /// ```
283 ///
284 /// This example collects into a [`Left`] variant:
285 #[cfg_attr(feature = "std", doc = "```rust")]
286 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
287 /// use std::collections::HashSet;
288 ///
289 /// use either_or_both::EitherOrBoth;
290 ///
291 /// let items: Vec<EitherOrBoth<u8, char>> = vec![EitherOrBoth::Left(2)];
292 /// let collected: EitherOrBoth<HashSet<u8>, HashSet<char>> =
293 /// items.into_iter().collect();
294 ///
295 /// assert_eq!(collected, EitherOrBoth::Left(HashSet::from([2])));
296 /// ```
297 ///
298 /// [`HashSets`]: std::collections::HashSet
299 /// [`Left`]: EitherOrBoth::Left
300 /// [`Right`]: EitherOrBoth::Right
301 /// [`Both`]: EitherOrBoth::Both
302 fn from_iter<T>(iter: T) -> Self
303 where
304 T: IntoIterator<Item = EitherOrBoth<K1, K2>>,
305 {
306 collect!(
307 iter;
308 cap => HashSet::with_capacity_and_hasher(cap, S1::default()),
309 HashSet::with_capacity_and_hasher(cap, S2::default());
310 fold => |(left, right), either| {
311 either.biapply(
312 |k1| {
313 left.insert(k1);
314 },
315 |k2| {
316 right.insert(k2);
317 },
318 );
319 (left, right)
320 })
321 }
322}
323
324#[cfg(feature = "indexmap")]
325impl<K1, K2, V1, V2, S1, S2> FromIterator<EitherOrBoth<(K1, V1), (K2, V2)>>
326 for EitherOrBoth<IndexMap<K1, V1, S1>, IndexMap<K2, V2, S2>>
327where
328 K1: core::hash::Hash + Eq,
329 K2: core::hash::Hash + Eq,
330 S1: core::hash::BuildHasher + Default,
331 S2: core::hash::BuildHasher + Default,
332{
333 /// Consumes an [`Iterator`] of [`EitherOrBoth`] items, collecting all left and right
334 /// values into separate [`IndexMaps`].
335 ///
336 /// - If only left values are present, returns [`Left`] with the left [`IndexMap`].
337 /// - If only right values are present, returns [`Right`] with the right [`IndexMap`].
338 /// - If none or both left and right values are present, returns [`Both`] with both
339 /// [`IndexMaps`].
340 ///
341 /// # Examples
342 ///
343 /// This example collects into a [`Both`] variant:
344 #[cfg_attr(feature = "std", doc = "```rust")]
345 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
346 /// use either_or_both::EitherOrBoth;
347 /// use indexmap::IndexMap;
348 ///
349 /// let items: Vec<EitherOrBoth<(&str, u8), (&str, char)>> = vec![
350 /// EitherOrBoth::Both(("both_l", 1), ("both_r", 'c')),
351 /// EitherOrBoth::Left(("left", 2)),
352 /// ];
353 ///
354 /// let collected: EitherOrBoth<IndexMap<&str, u8>, IndexMap<&str, char>> =
355 /// items.into_iter().collect();
356 ///
357 /// assert_eq!(
358 /// collected,
359 /// EitherOrBoth::Both(
360 /// IndexMap::from([("both_l", 1), ("left", 2)]),
361 /// IndexMap::from([("both_r", 'c')])
362 /// )
363 /// );
364 /// ```
365 ///
366 /// This example collects into a [`Left`] variant:
367 #[cfg_attr(feature = "std", doc = "```rust")]
368 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
369 /// use either_or_both::EitherOrBoth;
370 /// use indexmap::IndexMap;
371 ///
372 /// let items: Vec<EitherOrBoth<(&str, u8), (&str, char)>> =
373 /// vec![EitherOrBoth::Left(("left", 2))];
374 /// let collected: EitherOrBoth<IndexMap<&str, u8>, IndexMap<&str, char>> =
375 /// items.into_iter().collect();
376 ///
377 /// assert_eq!(
378 /// collected,
379 /// EitherOrBoth::Left(IndexMap::from([("left", 2)]),)
380 /// );
381 /// ```
382 ///
383 /// [`IndexMaps`]: indexmap::IndexMap
384 /// [`IndexMap`]: indexmap::IndexMap
385 /// [`Left`]: EitherOrBoth::Left
386 /// [`Right`]: EitherOrBoth::Right
387 /// [`Both`]: EitherOrBoth::Both
388 fn from_iter<T>(iter: T) -> Self
389 where
390 T: IntoIterator<Item = EitherOrBoth<(K1, V1), (K2, V2)>>,
391 {
392 collect!(
393 iter;
394 cap => IndexMap::with_capacity_and_hasher(cap, S1::default()),
395 IndexMap::with_capacity_and_hasher(cap, S2::default());
396 fold => |(left, right), either| {
397 either.biapply(
398 |(k1, v1)| {
399 left.insert(k1, v1);
400 },
401 |(k2, v2)| {
402 right.insert(k2, v2);
403 },
404 );
405 (left, right)
406 })
407 }
408}
409
410#[cfg(feature = "indexmap")]
411impl<K1, K2, S1, S2> FromIterator<EitherOrBoth<K1, K2>>
412 for EitherOrBoth<IndexSet<K1, S1>, IndexSet<K2, S2>>
413where
414 K1: core::hash::Hash + Eq,
415 K2: core::hash::Hash + Eq,
416 S1: core::hash::BuildHasher + Default,
417 S2: core::hash::BuildHasher + Default,
418{
419 /// Consumes an [`Iterator`] of [`EitherOrBoth`] items, collecting all left and right
420 /// values into separate [`IndexSets`].
421 ///
422 /// - If only left values are present, returns [`Left`] with the left [`IndexSet`].
423 /// - If only right values are present, returns [`Right`] with the right [`IndexSet`].
424 /// - If none or both left and right values are present, returns [`Both`] with both
425 /// [`IndexSets`].
426 ///
427 /// # Examples
428 ///
429 /// This example collects into a [`Both`] variant:
430 #[cfg_attr(feature = "std", doc = "```rust")]
431 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
432 /// use either_or_both::EitherOrBoth;
433 /// use indexmap::IndexSet;
434 ///
435 /// let items: Vec<EitherOrBoth<u8, char>> =
436 /// vec![EitherOrBoth::Both(1, 'c'), EitherOrBoth::Left(2)];
437 ///
438 /// let collected: EitherOrBoth<IndexSet<u8>, IndexSet<char>> =
439 /// items.into_iter().collect();
440 ///
441 /// assert_eq!(
442 /// collected,
443 /// EitherOrBoth::Both(IndexSet::from([1, 2]), IndexSet::from(['c']))
444 /// );
445 /// ```
446 ///
447 /// This example collects into a [`Left`] variant:
448 #[cfg_attr(feature = "std", doc = "```rust")]
449 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
450 /// use either_or_both::EitherOrBoth;
451 /// use indexmap::IndexSet;
452 ///
453 /// let items: Vec<EitherOrBoth<u8, char>> = vec![EitherOrBoth::Left(2)];
454 /// let collected: EitherOrBoth<IndexSet<u8>, IndexSet<char>> =
455 /// items.into_iter().collect();
456 ///
457 /// assert_eq!(collected, EitherOrBoth::Left(IndexSet::from([2])));
458 /// ```
459 ///
460 /// [`IndexSets`]: indexmap::IndexSet
461 /// [`IndexSet`]: indexmap::IndexSet
462 /// [`Left`]: EitherOrBoth::Left
463 /// [`Right`]: EitherOrBoth::Right
464 /// [`Both`]: EitherOrBoth::Both
465 fn from_iter<T>(iter: T) -> Self
466 where
467 T: IntoIterator<Item = EitherOrBoth<K1, K2>>,
468 {
469 collect!(
470 iter;
471 cap => indexmap::IndexSet::with_capacity_and_hasher(cap, S1::default()),
472 indexmap::IndexSet::with_capacity_and_hasher(cap, S2::default());
473 fold => |(left, right), either| {
474 either.biapply(
475 |k1| {
476 left.insert(k1);
477 },
478 |k2| {
479 right.insert(k2);
480 },
481 );
482 (left, right)
483 })
484 }
485}
486
487////////////////////////////////////////////////////////////////////////////////
488// FromIterator implementations for Either
489////////////////////////////////////////////////////////////////////////////////
490
491#[cfg(all(feature = "either", feature = "std"))]
492impl<L, R> FromIterator<Either<L, R>> for EitherOrBoth<Vec<L>, Vec<R>> {
493 /// Consumes an [`Iterator`] of [`Either`] items, collecting all left and right values
494 /// into separate [vectors].
495 ///
496 /// - If only left values are present, returns [`Left`] with the left [`Vec`].
497 /// - If only right values are present, returns [`Right`] with the right [`Vec`].
498 /// - If none or both left and right values are present, returns [`Both`] with both
499 /// [`Vec`]s.
500 ///
501 /// # Examples
502 ///
503 /// This example collects into a [`Both`] variant:
504 #[cfg_attr(feature = "std", doc = "```rust")]
505 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
506 /// use either_or_both::{Either, EitherOrBoth};
507 ///
508 /// let items: Vec<Either<u8, char>> = vec![Either::Left(1), Either::Right('c')];
509 /// let collected: EitherOrBoth<Vec<u8>, Vec<char>> = items.into_iter().collect();
510 ///
511 /// assert_eq!(collected, EitherOrBoth::Both(vec![1], vec!['c']));
512 /// ```
513 ///
514 /// This example collects into a [`Left`] variant:
515 #[cfg_attr(feature = "std", doc = "```rust")]
516 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
517 /// use either_or_both::{Either, EitherOrBoth};
518 ///
519 /// let items: Vec<Either<u8, char>> = vec![Either::Left(1), Either::Right('c')];
520 /// let collected: EitherOrBoth<Vec<u8>, Vec<char>> = items.into_iter().collect();
521 ///
522 /// assert_eq!(collected, EitherOrBoth::Both(vec![1], vec!['c']));
523 /// ```
524 ///
525 /// [vectors]: Vec
526 /// [`Left`]: EitherOrBoth::Left
527 /// [`Right`]: EitherOrBoth::Right
528 /// [`Both`]: EitherOrBoth::Both
529 fn from_iter<T: IntoIterator<Item = Either<L, R>>>(iter: T) -> Self {
530 collect!(
531 iter;
532 cap => Vec::with_capacity(cap), Vec::with_capacity(cap);
533 fold => |(left, right), either| {
534 either.biapply(|l| left.push(l), |r| right.push(r));
535 (left, right)
536 })
537 }
538}
539
540#[cfg(all(feature = "either", feature = "std"))]
541impl<K1, K2, V1, V2, S1, S2> FromIterator<Either<(K1, V1), (K2, V2)>>
542 for EitherOrBoth<HashMap<K1, V1, S1>, HashMap<K2, V2, S2>>
543where
544 K1: core::hash::Hash + Eq,
545 K2: core::hash::Hash + Eq,
546 S1: core::hash::BuildHasher + Default,
547 S2: core::hash::BuildHasher + Default,
548{
549 /// Consumes an [`Iterator`] of [`Either`] items, collecting all left and right values
550 /// into separate [`HashMaps`].
551 ///
552 /// - If only left values are present, returns [`Left`] with the left [`HashMap`].
553 /// - If only right values are present, returns [`Right`] with the right [`HashMap`].
554 /// - If none or both left and right values are present, returns [`Both`] with both
555 /// [`HashMaps`].
556 ///
557 /// # Examples
558 ///
559 /// This example collects into a [`Both`] variant:
560 #[cfg_attr(feature = "std", doc = "```rust")]
561 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
562 /// use std::collections::HashMap;
563 ///
564 /// use either_or_both::{Either, EitherOrBoth};
565 ///
566 /// let items: Vec<Either<(&str, u8), (&str, char)>> =
567 /// vec![Either::Right(("right", 'c')), Either::Left(("left", 2))];
568 ///
569 /// let collected: EitherOrBoth<HashMap<&str, u8>, HashMap<&str, char>> =
570 /// items.into_iter().collect();
571 ///
572 /// assert_eq!(
573 /// collected,
574 /// EitherOrBoth::Both(
575 /// HashMap::from([("left", 2)]),
576 /// HashMap::from([("right", 'c')])
577 /// )
578 /// );
579 /// ```
580 ///
581 /// This example collects into a [`Left`] variant:
582 #[cfg_attr(feature = "std", doc = "```rust")]
583 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
584 /// use std::collections::HashMap;
585 ///
586 /// use either_or_both::{Either, EitherOrBoth};
587 ///
588 /// let items: Vec<Either<(&str, u8), (&str, char)>> =
589 /// vec![Either::Left(("left", 2))];
590 /// let collected: EitherOrBoth<HashMap<&str, u8>, HashMap<&str, char>> =
591 /// items.into_iter().collect();
592 ///
593 /// assert_eq!(collected, EitherOrBoth::Left(HashMap::from([("left", 2)]),));
594 /// ```
595 ///
596 /// [`HashMaps`]: std::collections::HashMap
597 /// [`Left`]: EitherOrBoth::Left
598 /// [`Right`]: EitherOrBoth::Right
599 /// [`Both`]: EitherOrBoth::Both
600 fn from_iter<T>(iter: T) -> Self
601 where
602 T: IntoIterator<Item = Either<(K1, V1), (K2, V2)>>,
603 {
604 collect!(
605 iter;
606 cap => HashMap::with_capacity_and_hasher(cap, S1::default()),
607 HashMap::with_capacity_and_hasher(cap, S2::default());
608 fold => |(left, right), either| {
609 either.biapply(
610 |(k1, v1)| {
611 left.insert(k1, v1);
612 },
613 |(k2, v2)| {
614 right.insert(k2, v2);
615 },
616 );
617 (left, right)
618 })
619 }
620}
621
622#[cfg(all(feature = "either", feature = "std"))]
623impl<K1, K2, S1, S2> FromIterator<Either<K1, K2>> for EitherOrBoth<HashSet<K1, S1>, HashSet<K2, S2>>
624where
625 K1: core::hash::Hash + Eq,
626 K2: core::hash::Hash + Eq,
627 S1: core::hash::BuildHasher + Default,
628 S2: core::hash::BuildHasher + Default,
629{
630 /// Consumes an [`Iterator`] of [`Either`] items, collecting all left and right values
631 /// into separate [`HashSets`].
632 ///
633 /// - If only left values are present, returns [`Left`] with the left [`HashSet`].
634 /// - If only right values are present, returns [`Right`] with the right [`HashSet`].
635 /// - If none or both left and right values are present, returns [`Both`] with both
636 /// [`HashSets`].
637 ///
638 /// # Examples
639 ///
640 /// This example collects into a [`Both`] variant:
641 #[cfg_attr(feature = "std", doc = "```rust")]
642 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
643 /// use std::collections::HashSet;
644 ///
645 /// use either_or_both::{Either, EitherOrBoth};
646 ///
647 /// let items: Vec<Either<u8, char>> = vec![Either::Right('c'), Either::Left(2)];
648 ///
649 /// let collected: EitherOrBoth<HashSet<u8>, HashSet<char>> =
650 /// items.into_iter().collect();
651 ///
652 /// assert_eq!(
653 /// collected,
654 /// EitherOrBoth::Both(HashSet::from([2]), HashSet::from(['c']))
655 /// );
656 /// ```
657 ///
658 /// This example collects into a [`Left`] variant:
659 #[cfg_attr(feature = "std", doc = "```rust")]
660 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
661 /// use std::collections::HashSet;
662 ///
663 /// use either_or_both::{Either, EitherOrBoth};
664 ///
665 /// let items: Vec<Either<u8, char>> = vec![Either::Left(2)];
666 /// let collected: EitherOrBoth<HashSet<u8>, HashSet<char>> =
667 /// items.into_iter().collect();
668 ///
669 /// assert_eq!(collected, EitherOrBoth::Left(HashSet::from([2])));
670 /// ```
671 ///
672 /// [`HashSets`]: std::collections::HashSet
673 /// [`Left`]: EitherOrBoth::Left
674 /// [`Right`]: EitherOrBoth::Right
675 /// [`Both`]: EitherOrBoth::Both
676 fn from_iter<T>(iter: T) -> Self
677 where
678 T: IntoIterator<Item = Either<K1, K2>>,
679 {
680 collect!(
681 iter;
682 cap => HashSet::with_capacity_and_hasher(cap, S1::default()),
683 HashSet::with_capacity_and_hasher(cap, S2::default());
684 fold => |(left, right), either| {
685 either.biapply(
686 |k1| {
687 left.insert(k1);
688 },
689 |k2| {
690 right.insert(k2);
691 },
692 );
693 (left, right)
694 })
695 }
696}
697
698#[cfg(all(feature = "either", feature = "indexmap"))]
699impl<K1, K2, V1, V2, S1, S2> FromIterator<Either<(K1, V1), (K2, V2)>>
700 for EitherOrBoth<IndexMap<K1, V1, S1>, IndexMap<K2, V2, S2>>
701where
702 K1: core::hash::Hash + Eq,
703 K2: core::hash::Hash + Eq,
704 S1: core::hash::BuildHasher + Default,
705 S2: core::hash::BuildHasher + Default,
706{
707 /// Consumes an [`Iterator`] of [`Either`] items, collecting all left and right values
708 /// into separate [`IndexMaps`].
709 ///
710 /// - If only left values are present, returns [`Left`] with the left [`IndexMap`].
711 /// - If only right values are present, returns [`Right`] with the right [`IndexMap`].
712 /// - If none or both left and right values are present, returns [`Both`] with both
713 /// [`IndexMaps`].
714 ///
715 /// # Examples
716 ///
717 /// This example collects into a [`Both`] variant:
718 #[cfg_attr(feature = "std", doc = "```rust")]
719 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
720 /// use either_or_both::{Either, EitherOrBoth};
721 /// use indexmap::IndexMap;
722 ///
723 /// let items: Vec<Either<(&str, u8), (&str, char)>> =
724 /// vec![Either::Right(("right", 'c')), Either::Left(("left", 2))];
725 ///
726 /// let collected: EitherOrBoth<IndexMap<&str, u8>, IndexMap<&str, char>> =
727 /// items.into_iter().collect();
728 ///
729 /// assert_eq!(
730 /// collected,
731 /// EitherOrBoth::Both(
732 /// IndexMap::from([("left", 2)]),
733 /// IndexMap::from([("right", 'c')])
734 /// )
735 /// );
736 /// ```
737 ///
738 /// This example collects into a [`Left`] variant:
739 #[cfg_attr(feature = "std", doc = "```rust")]
740 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
741 /// use either_or_both::{Either, EitherOrBoth};
742 /// use indexmap::IndexMap;
743 ///
744 /// let items: Vec<Either<(&str, u8), (&str, char)>> =
745 /// vec![Either::Left(("left", 2))];
746 /// let collected: EitherOrBoth<IndexMap<&str, u8>, IndexMap<&str, char>> =
747 /// items.into_iter().collect();
748 ///
749 /// assert_eq!(
750 /// collected,
751 /// EitherOrBoth::Left(IndexMap::from([("left", 2)]),)
752 /// );
753 /// ```
754 ///
755 /// [`IndexMaps`]: indexmap::IndexMap
756 /// [`IndexMap`]: indexmap::IndexMap
757 /// [`Left`]: EitherOrBoth::Left
758 /// [`Right`]: EitherOrBoth::Right
759 /// [`Both`]: EitherOrBoth::Both
760 fn from_iter<T>(iter: T) -> Self
761 where
762 T: IntoIterator<Item = Either<(K1, V1), (K2, V2)>>,
763 {
764 collect!(
765 iter;
766 cap => indexmap::IndexMap::with_capacity_and_hasher(cap, S1::default()),
767 indexmap::IndexMap::with_capacity_and_hasher(cap, S2::default());
768 fold => |(left, right), either| {
769 either.biapply(
770 |(k1, v1)| {
771 left.insert(k1, v1);
772 },
773 |(k2, v2)| {
774 right.insert(k2, v2);
775 },
776 );
777 (left, right)
778 })
779 }
780}
781
782#[cfg(all(feature = "either", feature = "indexmap"))]
783impl<K1, K2, S1, S2> FromIterator<Either<K1, K2>>
784 for EitherOrBoth<IndexSet<K1, S1>, IndexSet<K2, S2>>
785where
786 K1: core::hash::Hash + Eq,
787 K2: core::hash::Hash + Eq,
788 S1: core::hash::BuildHasher + Default,
789 S2: core::hash::BuildHasher + Default,
790{
791 /// Consumes an [`Iterator`] of [`Either`] items, collecting all left and right values
792 /// into separate [`IndexSets`].
793 ///
794 /// - If only left values are present, returns [`Left`] with the left [`IndexSet`].
795 /// - If only right values are present, returns [`Right`] with the right [`IndexSet`].
796 /// - If none or both left and right values are present, returns [`Both`] with both
797 /// [`IndexSets`].
798 ///
799 /// # Examples
800 ///
801 /// This example collects into a [`Both`] variant:
802 #[cfg_attr(feature = "std", doc = "```rust")]
803 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
804 /// use either_or_both::{Either, EitherOrBoth};
805 /// use indexmap::IndexSet;
806 ///
807 /// let items: Vec<Either<u8, char>> = vec![Either::Right('c'), Either::Left(2)];
808 /// let collected: EitherOrBoth<IndexSet<u8>, IndexSet<char>> =
809 /// items.into_iter().collect();
810 ///
811 /// assert_eq!(
812 /// collected,
813 /// EitherOrBoth::Both(IndexSet::from([2]), IndexSet::from(['c']))
814 /// );
815 /// ```
816 ///
817 /// This example collects into a [`Left`] variant:
818 #[cfg_attr(feature = "std", doc = "```rust")]
819 #[cfg_attr(not(feature = "std"), doc = "```rust,ignore")]
820 /// use either_or_both::{Either, EitherOrBoth};
821 /// use indexmap::IndexSet;
822 ///
823 /// let items: Vec<Either<u8, char>> = vec![Either::Left(2)];
824 /// let collected: EitherOrBoth<IndexSet<u8>, IndexSet<char>> =
825 /// items.into_iter().collect();
826 ///
827 /// assert_eq!(collected, EitherOrBoth::Left(IndexSet::from([2])));
828 /// ```
829 ///
830 /// [`IndexSets`]: indexmap::IndexSet
831 /// [`IndexSet`]: indexmap::IndexSet
832 /// [`Left`]: EitherOrBoth::Left
833 /// [`Right`]: EitherOrBoth::Right
834 /// [`Both`]: EitherOrBoth::Both
835 fn from_iter<T>(iter: T) -> Self
836 where
837 T: IntoIterator<Item = Either<K1, K2>>,
838 {
839 collect!(
840 iter;
841 cap => IndexSet::with_capacity_and_hasher(cap, S1::default()),
842 IndexSet::with_capacity_and_hasher(cap, S2::default());
843 fold => |(left, right), either| {
844 either.biapply(
845 |k1| {
846 left.insert(k1);
847 },
848 |k2| {
849 right.insert(k2);
850 },
851 );
852 (left, right)
853 })
854 }
855}
856
857////////////////////////////////////////////////////////////////////////////////
858// From/TryFrom/... implementations
859////////////////////////////////////////////////////////////////////////////////
860
861#[cfg(feature = "std")]
862impl<L, R> EitherOrBoth<L, R>
863where
864 L: Error,
865 R: Error,
866{
867 /// Returns both error sources as a pair, complementing [`Error::source`]
868 ///
869 /// Since [`Error::source`] returns only the left source from the `Both` variant this
870 /// method can be used to retrieve both sources, if any.
871 ///
872 /// # Examples
873 ///
874 /// ```
875 /// use core::fmt::{Display, Formatter, Result};
876 /// use std::error::Error;
877 ///
878 /// use either_or_both::EitherOrBoth;
879 ///
880 /// #[derive(Debug)]
881 /// struct SuperError {};
882 /// impl Error for SuperError {};
883 /// impl Display for SuperError {
884 /// fn fmt(&self, f: &mut Formatter<'_>) -> Result {
885 /// f.write_str("super error")
886 /// }
887 /// }
888 ///
889 /// #[derive(Debug)]
890 /// struct ErrLeft {
891 /// source: Option<SuperError>,
892 /// };
893 /// impl Display for ErrLeft {
894 /// fn fmt(&self, f: &mut Formatter<'_>) -> Result {
895 /// f.write_str("left")
896 /// }
897 /// }
898 /// impl Error for ErrLeft {
899 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
900 /// self.source.as_ref().map(|e| e as &dyn Error)
901 /// }
902 /// }
903 ///
904 /// #[derive(Debug)]
905 /// struct ErrRight {
906 /// source: Option<SuperError>,
907 /// };
908 /// impl Display for ErrRight {
909 /// fn fmt(&self, f: &mut Formatter<'_>) -> Result {
910 /// f.write_str("right")
911 /// }
912 /// }
913 /// impl Error for ErrRight {
914 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
915 /// self.source.as_ref().map(|e| e as &dyn Error)
916 /// }
917 /// }
918 ///
919 /// let left: EitherOrBoth<ErrLeft, ErrRight> = EitherOrBoth::Left(ErrLeft { source: None });
920 /// assert!(matches!(left.error_sources(), (None, None)));
921 ///
922 /// let right: EitherOrBoth<ErrLeft, ErrRight> = EitherOrBoth::Right(ErrRight {
923 /// source: Some(SuperError {}),
924 /// });
925 /// assert!(matches!(right.error_sources(), (None, Some(_))));
926 ///
927 /// let both: EitherOrBoth<ErrLeft, ErrRight> = EitherOrBoth::Both(
928 /// ErrLeft { source: None },
929 /// ErrRight {
930 /// source: Some(SuperError {}),
931 /// },
932 /// );
933 /// assert!(matches!(both.error_sources(), (None, Some(_))));
934 /// ```
935 ///
936 /// [`Error::source`]: std::error::Error::source
937 pub fn error_sources(
938 &self,
939 ) -> (
940 Option<&(dyn Error + 'static)>,
941 Option<&(dyn Error + 'static)>,
942 ) {
943 match self {
944 Self::Left(l) => (l.source(), None),
945 Self::Right(r) => (None, r.source()),
946 Self::Both(l, r) => (l.source(), r.source()),
947 }
948 }
949}
950
951impl<L, R> Display for EitherOrBoth<L, R>
952where
953 L: Display,
954 R: Display,
955{
956 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
957 match self {
958 Self::Both(l, r) => write!(f, "{l}\n{r}"),
959 Self::Left(l) => l.fmt(f),
960 Self::Right(r) => r.fmt(f),
961 }
962 }
963}
964
965#[cfg(feature = "std")]
966impl<L, R> Error for EitherOrBoth<L, R>
967where
968 L: Error,
969 R: Error,
970{
971 /// Returns the lower-level source of this `EitherOrBoth` error, if any
972 ///
973 /// In case there are two error sources from the `Both` variant, the left source takes
974 /// precedence. If you need both error sources use [`EitherOrBoth::error_sources`] instead.
975 ///
976 /// # Examples
977 ///
978 /// ```
979 /// use core::fmt::{Display, Formatter, Result};
980 /// use std::error::Error;
981 ///
982 /// use either_or_both::EitherOrBoth;
983 ///
984 /// #[derive(Debug)]
985 /// struct SuperError {}
986 /// impl Error for SuperError {}
987 /// impl Display for SuperError {
988 /// fn fmt(&self, f: &mut Formatter<'_>) -> Result {
989 /// f.write_str("super error")
990 /// }
991 /// }
992 ///
993 /// #[derive(Debug)]
994 /// struct SomeError {
995 /// source: Option<SuperError>,
996 /// };
997 /// impl Display for SomeError {
998 /// fn fmt(&self, f: &mut Formatter<'_>) -> Result {
999 /// f.write_str("some error")
1000 /// }
1001 /// }
1002 /// impl Error for SomeError {
1003 /// fn source(&self) -> Option<&(dyn Error + 'static)> {
1004 /// self.source.as_ref().map(|e| e as &dyn Error)
1005 /// }
1006 /// }
1007 ///
1008 /// let left: EitherOrBoth<SomeError> = EitherOrBoth::Left(SomeError { source: None });
1009 /// assert!(matches!(left.source(), None));
1010 ///
1011 /// let right: EitherOrBoth<SomeError> = EitherOrBoth::Right(SomeError {
1012 /// source: Some(SuperError {}),
1013 /// });
1014 /// assert!(matches!(right.source(), Some(_)));
1015 ///
1016 /// // Since left has no source, this method returns None even if the right error has a source
1017 /// let both: EitherOrBoth<SomeError> = EitherOrBoth::Both(
1018 /// SomeError { source: None },
1019 /// SomeError {
1020 /// source: Some(SuperError {}),
1021 /// },
1022 /// );
1023 /// assert!(matches!(both.source(), None));
1024 /// ```
1025 ///
1026 /// [`Error::source`]: std::error::Error::source
1027 fn source(&self) -> Option<&(dyn Error + 'static)> {
1028 match self {
1029 Self::Right(r) => r.source(),
1030 Self::Left(l) | Self::Both(l, _) => l.source(),
1031 }
1032 }
1033}
1034
1035impl<L, R> Ord for EitherOrBoth<L, R>
1036where
1037 L: Ord,
1038 R: Ord,
1039{
1040 /// Compares two [`EitherOrBoth`] values using the ordering `Left < Both < Right`.
1041 ///
1042 /// This differs from a derived `Ord` implementation, which would order by discriminant
1043 /// (`Both < Left < Right`). When both values are the same variant, the inner values
1044 /// are compared directly. For the [`Both`] variant, the left values are compared
1045 /// first, and only if equal are the right values compared.
1046 ///
1047 /// # Examples
1048 ///
1049 /// ```
1050 /// use either_or_both::EitherOrBoth;
1051 ///
1052 /// // Left is less than Both and Right
1053 /// assert!(EitherOrBoth::<u8>::Left(5) < EitherOrBoth::Both(1, 1));
1054 /// assert!(EitherOrBoth::<u8>::Left(5) < EitherOrBoth::Right(1));
1055 ///
1056 /// // Both is less than Right
1057 /// assert!(EitherOrBoth::Both(1, 1) < EitherOrBoth::<u8, u8>::Right(1));
1058 ///
1059 /// // Same variants compare inner values
1060 /// assert!(EitherOrBoth::<u8>::Left(1) < EitherOrBoth::Left(2));
1061 /// assert!(EitherOrBoth::<u8>::Right(1) < EitherOrBoth::Right(2));
1062 /// assert!(EitherOrBoth::Both(1, 1) < EitherOrBoth::Both(2, 1));
1063 /// assert!(EitherOrBoth::Both(1, 1) < EitherOrBoth::Both(1, 2));
1064 /// ```
1065 ///
1066 /// [`Both`]: EitherOrBoth::Both
1067 fn cmp(&self, other: &Self) -> Ordering {
1068 // The implementation of Left < Both < Right
1069 match (self, other) {
1070 (Self::Left(a), Self::Left(b)) => a.cmp(b),
1071 (Self::Left(_), _) | (Self::Both(_, _), Self::Right(_)) => Ordering::Less,
1072 (Self::Both(l1, r1), Self::Both(l2, r2)) => l1.cmp(l2).then(r1.cmp(r2)),
1073 (Self::Right(a), Self::Right(b)) => a.cmp(b),
1074 (Self::Both(_, _), Self::Left(_)) | (Self::Right(_), _) => Ordering::Greater,
1075 }
1076 }
1077}
1078
1079impl<L, R> PartialOrd for EitherOrBoth<L, R>
1080where
1081 L: Ord,
1082 R: Ord,
1083{
1084 /// Compares two [`EitherOrBoth`] values using the same ordering as [`Ord::cmp`].
1085 ///
1086 /// [`EitherOrBoth`] always has a total ordering, so this always returns `Some`.
1087 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1088 Some(self.cmp(other))
1089 }
1090}
1091
1092#[cfg(feature = "either")]
1093impl<L, R> From<Either<L, R>> for EitherOrBoth<L, R> {
1094 fn from(value: Either<L, R>) -> Self {
1095 match value {
1096 Either::Left(left) => Self::Left(left),
1097 Either::Right(right) => Self::Right(right),
1098 }
1099 }
1100}
1101
1102impl<L, R> From<(L, R)> for EitherOrBoth<L, R> {
1103 fn from((left, right): (L, R)) -> Self {
1104 Self::Both(left, right)
1105 }
1106}
1107
1108impl<L, R> From<(Option<L>, R)> for EitherOrBoth<L, R> {
1109 fn from((left, right): (Option<L>, R)) -> Self {
1110 match left {
1111 Some(left) => Self::Both(left, right),
1112 None => Self::Right(right),
1113 }
1114 }
1115}
1116
1117impl<L, R> From<(L, Option<R>)> for EitherOrBoth<L, R> {
1118 fn from((left, right): (L, Option<R>)) -> Self {
1119 match right {
1120 Some(right) => Self::Both(left, right),
1121 None => Self::Left(left),
1122 }
1123 }
1124}
1125
1126impl<L, R> TryFrom<(Option<L>, Option<R>)> for EitherOrBoth<L, R> {
1127 type Error = TryFromOptionsError;
1128
1129 fn try_from(value: (Option<L>, Option<R>)) -> Result<Self, Self::Error> {
1130 match value {
1131 (None, None) => Err(TryFromOptionsError),
1132 (None, Some(right)) => Ok(Self::Right(right)),
1133 (Some(left), None) => Ok(Self::Left(left)),
1134 (Some(left), Some(right)) => Ok(Self::Both(left, right)),
1135 }
1136 }
1137}