1use super::{MultiQueryDatabase, WithVersion};
2use crate::{
3 multi::{Entries, EntriesMut, MultiQuerier, MultiQueriers, MultiQueriersMut},
4 value::RepositoryName,
5};
6use arch_pkg_text::{
7 desc::{Query, QueryMut},
8 value::DependencyName,
9};
10use core::iter::FusedIterator;
11
12#[derive(Debug, Clone)]
17pub struct AlternativeProviders<'r, 'query, 'name, Querier> {
18 target: DependencyName<'name>,
19 current: Option<Entries<'r, 'query, Querier>>, queriers: MultiQueriers<'r, 'query, Querier>,
21}
22
23impl<'r, 'query, 'name, Querier> AlternativeProviders<'r, 'query, 'name, Querier> {
24 fn new(target: DependencyName<'name>, queriers: MultiQueriers<'r, 'query, Querier>) -> Self {
26 let mut result = AlternativeProviders {
27 target,
28 current: None,
29 queriers,
30 };
31 result.change_querier();
32 result
33 }
34
35 fn change_querier(&mut self) {
37 self.current = self.queriers.next().map(MultiQuerier::entries);
38 }
39}
40
41impl<'r, 'query, 'name, Querier: Query<'r>> Iterator
42 for AlternativeProviders<'r, 'query, 'name, Querier>
43{
44 type Item = (RepositoryName<'query>, &'r WithVersion<'query, Querier>);
45 fn next(&mut self) -> Option<Self::Item> {
46 loop {
47 if cfg!(debug_assertions) && self.current.is_none() && self.queriers.next().is_some() {
48 panic!("Invariant violated! `current` was emptied before `queriers`");
49 }
50
51 for (repository, querier) in self.current.as_mut()? {
52 let found = querier
53 .provides()
54 .into_iter()
55 .flatten()
56 .map(|provide| provide.components())
57 .any(|(name, _)| name == self.target);
58 if found {
59 return Some((repository, querier));
60 }
61 }
62
63 self.change_querier();
64 }
65 }
66}
67
68impl<'r, 'query, 'name, Querier: Query<'r>> FusedIterator
69 for AlternativeProviders<'r, 'query, 'name, Querier>
70{
71}
72
73#[derive(Debug)]
78pub struct AlternativeProvidersMut<'r, 'query, 'name, Querier> {
79 target: DependencyName<'name>,
80 current: Option<EntriesMut<'r, 'query, Querier>>, queriers: MultiQueriersMut<'r, 'query, Querier>,
82}
83
84impl<'r, 'query, 'name, Querier> AlternativeProvidersMut<'r, 'query, 'name, Querier> {
85 fn new(target: DependencyName<'name>, queriers: MultiQueriersMut<'r, 'query, Querier>) -> Self {
87 let mut result = AlternativeProvidersMut {
88 target,
89 current: None,
90 queriers,
91 };
92 result.change_querier();
93 result
94 }
95
96 fn change_querier(&mut self) {
98 self.current = self.queriers.next().map(MultiQuerier::entries_mut);
99 }
100}
101
102impl<'r, 'query, 'name, Querier: QueryMut<'r>> Iterator
103 for AlternativeProvidersMut<'r, 'query, 'name, Querier>
104{
105 type Item = (RepositoryName<'query>, &'r mut WithVersion<'query, Querier>);
106 fn next(&mut self) -> Option<Self::Item> {
107 loop {
108 if cfg!(debug_assertions) && self.current.is_none() && self.queriers.next().is_some() {
109 panic!("Invariant violated! `current` was emptied before `queriers`");
110 }
111
112 for (repository, querier) in self.current.as_mut()? {
113 let found = querier
114 .provides_mut()
115 .into_iter()
116 .flatten()
117 .map(|provide| provide.components())
118 .any(|(name, _)| name == self.target);
119 if found {
120 return Some((repository, querier));
121 }
122 }
123
124 self.change_querier();
125 }
126 }
127}
128
129impl<'r, 'query, 'name, Querier: QueryMut<'r>> FusedIterator
130 for AlternativeProvidersMut<'r, 'query, 'name, Querier>
131{
132}
133
134impl<'query, Querier> MultiQueryDatabase<'query, Querier> {
135 pub fn alternative_providers<'r, 'name>(
142 &'r self,
143 target: DependencyName<'name>,
144 ) -> AlternativeProviders<'r, 'query, 'name, Querier> {
145 AlternativeProviders::new(target, self.queriers())
146 }
147
148 pub fn alternative_providers_mut<'r, 'name>(
155 &'r mut self,
156 target: DependencyName<'name>,
157 ) -> AlternativeProvidersMut<'r, 'query, 'name, Querier> {
158 AlternativeProvidersMut::new(target, self.queriers_mut())
159 }
160}