rosu_mods/
intersection.rs1use std::{
2 cmp::{min, Ordering},
3 collections::{btree_map::Iter as TreeIter, btree_set::Iter as SetIter},
4};
5
6use crate::{
7 generated_mods::{GameMod, GameModIntermode},
8 order::GameModOrder,
9};
10
11pub(super) enum IntersectionInner<I, A> {
12 Stitch(Stitch<I>),
13 Answer(Option<A>),
14}
15
16impl<I, A> IntersectionInner<I, A> {
17 pub(super) const fn new_stitch(a: I, b: I) -> Self {
18 Self::Stitch(Stitch { a, b })
19 }
20}
21
22pub(super) struct Stitch<I> {
23 a: I,
24 b: I,
25}
26
27pub struct GameModsIntersection<'m> {
35 pub(super) inner: IntersectionInner<TreeIter<'m, GameModOrder, GameMod>, &'m GameMod>,
36}
37
38impl<'m> Iterator for GameModsIntersection<'m> {
39 type Item = &'m GameMod;
40
41 fn next(&mut self) -> Option<Self::Item> {
42 match &mut self.inner {
43 IntersectionInner::Stitch(Stitch { a, b }) => {
44 let mut a_next = a.next()?;
45 let mut b_next = b.next()?;
46
47 loop {
48 match a_next.0.cmp(b_next.0) {
49 Ordering::Less => a_next = a.next()?,
50 Ordering::Greater => b_next = b.next()?,
51 Ordering::Equal => return Some(a_next.1),
52 }
53 }
54 }
55 IntersectionInner::Answer(answer) => answer.take(),
56 }
57 }
58
59 fn size_hint(&self) -> (usize, Option<usize>) {
60 match &self.inner {
61 IntersectionInner::Stitch(Stitch { a, b }) => (0, Some(min(a.len(), b.len()))),
62 IntersectionInner::Answer(None) => (0, Some(0)),
63 IntersectionInner::Answer(Some(_)) => (1, Some(1)),
64 }
65 }
66
67 fn min(mut self) -> Option<Self::Item> {
68 self.next()
69 }
70}
71
72pub struct GameModsIntermodeIntersection<'m> {
79 pub(super) inner: IntersectionInner<SetIter<'m, GameModIntermode>, GameModIntermode>,
80}
81
82impl Iterator for GameModsIntermodeIntersection<'_> {
83 type Item = GameModIntermode;
84
85 fn next(&mut self) -> Option<Self::Item> {
86 match &mut self.inner {
87 IntersectionInner::Stitch(Stitch { a, b }) => {
88 let mut a_next = a.next()?;
89 let mut b_next = b.next()?;
90
91 loop {
92 match a_next.cmp(b_next) {
93 Ordering::Less => a_next = a.next()?,
94 Ordering::Greater => b_next = b.next()?,
95 Ordering::Equal => return Some(*a_next),
96 }
97 }
98 }
99 IntersectionInner::Answer(answer) => answer.take(),
100 }
101 }
102
103 fn size_hint(&self) -> (usize, Option<usize>) {
104 match &self.inner {
105 IntersectionInner::Stitch(Stitch { a, b }) => (0, Some(min(a.len(), b.len()))),
106 IntersectionInner::Answer(None) => (0, Some(0)),
107 IntersectionInner::Answer(Some(_)) => (1, Some(1)),
108 }
109 }
110
111 fn min(mut self) -> Option<Self::Item> {
112 self.next()
113 }
114}