Skip to main content

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}