Skip to content

Commit cf070a1

Browse files
committed
feat(utils): revive AlpmExt yet again
This required implementing some custom iterator structs, since `impl Foo` is not allowed for the return types of trait methods.
1 parent 1fc2aa3 commit cf070a1

File tree

1 file changed

+65
-15
lines changed

1 file changed

+65
-15
lines changed

alpm-utils/src/alpm.rs

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,74 @@
11
//! Extension methods for the [`Alpm`] type.
22
33
use crate::DbListExt;
4-
use alpm::{Alpm, Package};
4+
use alpm::{Alpm, AlpmList, Db, IntoIter, Package};
55

6-
/// All official packages.
7-
pub fn native_packages(alpm: &Alpm) -> impl Iterator<Item = Package<'_>> {
8-
let syncs = alpm.syncdbs();
6+
/// Extension methods for [`Alpm`] which aren't critical enough to live in the
7+
/// main crate, directly within `Alpm`.
8+
pub trait AlpmExt {
9+
/// An iterator of [`Package`]s that are found in "sync databases",
10+
/// typically registered in one's `pacman.conf`.
11+
fn native_packages<'a>(&'a self) -> NativePkgs<'a>;
912

10-
alpm.localdb()
11-
.pkgs()
12-
.into_iter()
13-
.filter_map(move |p| syncs.pkg(p.name()).ok())
13+
/// The opposite of [`AlpmExt::native_packages`]; installed packages that
14+
/// aren't found in any registered "sync database".
15+
fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a>;
1416
}
1517

16-
/// All foreign packages as an `Iterator`.
17-
pub fn foreign_packages(alpm: &Alpm) -> impl Iterator<Item = Package<'_>> {
18-
let syncs = alpm.syncdbs();
18+
impl AlpmExt for Alpm {
19+
fn native_packages<'a>(&'a self) -> NativePkgs<'a> {
20+
NativePkgs::new(self)
21+
}
1922

20-
alpm.localdb()
21-
.pkgs()
22-
.into_iter()
23-
.filter(move |p| syncs.pkg(p.name()).is_err())
23+
fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a> {
24+
ForeignPkgs::new(self)
25+
}
26+
}
27+
28+
/// [`Package`]s that are found in registered "sync databases".
29+
pub struct NativePkgs<'a> {
30+
local: IntoIter<'a, Package<'a>>,
31+
sync: AlpmList<'a, Db<'a>>,
32+
}
33+
34+
impl<'a> NativePkgs<'a> {
35+
fn new(alpm: &'a Alpm) -> NativePkgs<'a> {
36+
let local = alpm.localdb().pkgs().into_iter();
37+
let sync = alpm.syncdbs();
38+
39+
NativePkgs { local, sync }
40+
}
41+
}
42+
43+
impl<'a> Iterator for NativePkgs<'a> {
44+
type Item = Package<'a>;
45+
46+
fn next(&mut self) -> Option<Self::Item> {
47+
let s = self.sync;
48+
self.local.find(|p| s.pkg(p.name()).is_ok())
49+
}
50+
}
51+
52+
/// Installed [`Package`]s that are _not_ found in registered "sync databases".
53+
pub struct ForeignPkgs<'a> {
54+
local: IntoIter<'a, Package<'a>>,
55+
sync: AlpmList<'a, Db<'a>>,
56+
}
57+
58+
impl<'a> ForeignPkgs<'a> {
59+
fn new(alpm: &'a Alpm) -> ForeignPkgs<'a> {
60+
let local = alpm.localdb().pkgs().into_iter();
61+
let sync = alpm.syncdbs();
62+
63+
ForeignPkgs { local, sync }
64+
}
65+
}
66+
67+
impl<'a> Iterator for ForeignPkgs<'a> {
68+
type Item = Package<'a>;
69+
70+
fn next(&mut self) -> Option<Self::Item> {
71+
let s = self.sync;
72+
self.local.find(|p| s.pkg(p.name()).is_err())
73+
}
2474
}

0 commit comments

Comments
 (0)