arch_pkg_db/single/
providers.rs

1use super::QueryDatabase;
2use crate::single::{Queriers, QueriersMut};
3use arch_pkg_text::{
4    desc::{Query, QueryMut},
5    value::DependencyName,
6};
7use core::iter::FusedIterator;
8
9/// [Iterator] over all immutable queriers of packages which list a certain [`DependencyName`] in their
10/// [`provides`](Query::provides) array.
11///
12/// This iterator is created by calling [`QueryDatabase::alternative_providers`].
13#[derive(Debug, Clone)]
14pub struct AlternativeProviders<'r, 'name, Querier> {
15    target: DependencyName<'name>,
16    queriers: Queriers<'r, 'name, Querier>,
17}
18
19impl<'r, 'name, Querier: Query<'r>> Iterator for AlternativeProviders<'r, 'name, Querier> {
20    type Item = &'r Querier;
21
22    fn next(&mut self) -> Option<Self::Item> {
23        self.queriers.find(|querier| {
24            querier
25                .provides()
26                .into_iter()
27                .flatten()
28                .map(|provide| provide.components())
29                .any(|(name, _)| name == self.target)
30        })
31    }
32
33    fn size_hint(&self) -> (usize, Option<usize>) {
34        let (_, max) = self.queriers.size_hint();
35        (0, max)
36    }
37}
38
39impl<'r, 'name, Querier: Query<'r>> FusedIterator for AlternativeProviders<'r, 'name, Querier> {}
40
41/// [Iterator] over all mutable queriers of packages which list a certain [`DependencyName`] in their
42/// [`provides`](QueryMut::provides_mut) array.
43///
44/// This iterator is created by calling [`QueryDatabase::alternative_providers_mut`].
45#[derive(Debug)]
46pub struct AlternativeProvidersMut<'r, 'name, Querier> {
47    target: DependencyName<'name>,
48    queriers: QueriersMut<'r, 'name, Querier>,
49}
50
51impl<'r, 'name, Querier: QueryMut<'r>> Iterator for AlternativeProvidersMut<'r, 'name, Querier> {
52    type Item = &'r mut Querier;
53
54    fn next(&mut self) -> Option<Self::Item> {
55        self.queriers.find_map(|querier| {
56            querier
57                .provides_mut()
58                .into_iter()
59                .flatten()
60                .map(|provide| provide.components())
61                .any(|(name, _)| name == self.target)
62                .then_some(querier)
63        })
64    }
65
66    fn size_hint(&self) -> (usize, Option<usize>) {
67        let (_, max) = self.queriers.size_hint();
68        (0, max)
69    }
70}
71
72impl<'r, 'name, Querier: QueryMut<'r>> FusedIterator
73    for AlternativeProvidersMut<'r, 'name, Querier>
74{
75}
76
77impl<Querier> QueryDatabase<'_, Querier> {
78    /// Get an iterator over all immutable queriers of packages which list a certain [`DependencyName`] in their
79    /// [`provides`](Query::provides) array.
80    ///
81    /// This method is prefixed with "alternative" because a package doesn't usually list itself in its own `provides`,
82    /// and consequently, would usually be excluded from this iterator. Beware that if it does list itself, its own
83    /// name would be included.
84    pub fn alternative_providers<'a>(
85        &'a self,
86        target: DependencyName<'a>,
87    ) -> AlternativeProviders<'a, 'a, Querier> {
88        let queriers = self.queriers();
89        AlternativeProviders { target, queriers }
90    }
91
92    /// Get an iterator over all mutable queriers of packages which list a certain [`DependencyName`] in their
93    /// [`provides`](QueryMut::provides_mut) array.
94    ///
95    /// This method is prefixed with "alternative" because a package doesn't usually list itself in its own `provides`,
96    /// and consequently, would usually be excluded from this iterator. Beware that if it does list itself, its own
97    /// name would be included.
98    pub fn alternative_providers_mut<'a>(
99        &'a mut self,
100        target: DependencyName<'a>,
101    ) -> AlternativeProvidersMut<'a, 'a, Querier> {
102        let queriers = self.queriers_mut();
103        AlternativeProvidersMut { target, queriers }
104    }
105}