rust_apt/iterators/
version.rs1use std::cell::OnceCell;
2use std::cmp::Ordering;
3use std::collections::HashMap;
4use std::fmt;
5
6use cxx::UniquePtr;
7
8use crate::raw::{IntoRawIter, VerIterator};
9use crate::util::cmp_versions;
10use crate::{
11 Cache, DepType, Dependency, Package, PackageFile, PackageRecords, Provider, VersionFile,
12 create_depends_map,
13};
14
15pub struct Version<'a> {
17 pub(crate) ptr: UniquePtr<VerIterator>,
18 cache: &'a Cache,
19 depends_map: OnceCell<HashMap<DepType, Vec<Dependency<'a>>>>,
20}
21
22impl Clone for Version<'_> {
23 fn clone(&self) -> Self {
24 Self {
25 ptr: unsafe { self.ptr.unique() },
26 cache: self.cache,
27 depends_map: self.depends_map.clone(),
28 }
29 }
30}
31
32impl<'a> Version<'a> {
33 pub fn new(ptr: UniquePtr<VerIterator>, cache: &'a Cache) -> Version<'a> {
34 Version {
35 ptr,
36 cache,
37 depends_map: OnceCell::new(),
38 }
39 }
40
41 pub fn provides(&self) -> impl Iterator<Item = Provider<'a>> {
43 unsafe { self.ptr.provides() }
44 .raw_iter()
45 .map(|p| Provider::new(p, self.cache))
46 }
47
48 pub fn version_files(&self) -> impl Iterator<Item = VersionFile<'a>> {
49 unsafe { self.ptr.version_files() }
50 .raw_iter()
51 .map(|v| VersionFile::new(v, self.cache))
52 }
53
54 pub fn package_files(&self) -> impl Iterator<Item = PackageFile<'a>> {
56 self.version_files().map(|v| v.package_file())
57 }
58
59 pub fn parent(&self) -> Package<'a> { Package::new(self.cache, unsafe { self.parent_pkg() }) }
61
62 pub fn depends_map(&self) -> &HashMap<DepType, Vec<Dependency<'a>>> {
88 self.depends_map
89 .get_or_init(|| create_depends_map(self.cache, unsafe { self.depends().make_safe() }))
90 }
91
92 pub fn get_depends(&self, key: &DepType) -> Option<&Vec<Dependency<'a>>> {
96 self.depends_map().get(key)
97 }
98
99 pub fn enhances(&self) -> Option<&Vec<Dependency<'a>>> { self.get_depends(&DepType::Enhances) }
101
102 pub fn dependencies(&self) -> Option<Vec<&Dependency<'a>>> {
105 let mut ret_vec: Vec<&Dependency> = Vec::new();
106
107 for dep_type in [DepType::Depends, DepType::PreDepends] {
108 if let Some(dep_list) = self.get_depends(&dep_type) {
109 for dep in dep_list {
110 ret_vec.push(dep)
111 }
112 }
113 }
114
115 if ret_vec.is_empty() {
116 return None;
117 }
118 Some(ret_vec)
119 }
120
121 pub fn recommends(&self) -> Option<&Vec<Dependency<'a>>> {
123 self.get_depends(&DepType::Recommends)
124 }
125
126 pub fn suggests(&self) -> Option<&Vec<Dependency<'a>>> { self.get_depends(&DepType::Suggests) }
128
129 fn desc_lookup(&self) -> Option<&PackageRecords> {
131 let desc = unsafe { self.translated_desc().make_safe()? };
132 Some(self.cache.records().desc_lookup(&desc))
133 }
134
135 pub fn description(&self) -> Option<String> { self.desc_lookup()?.long_desc() }
137
138 pub fn summary(&self) -> Option<String> { self.desc_lookup()?.short_desc() }
140
141 pub fn get_record<T: ToString + ?Sized>(&self, field: &T) -> Option<String> {
160 self.version_files()
161 .next()?
162 .lookup()
163 .get_field(field.to_string())
164 }
165
166 pub fn hash<T: ToString + ?Sized>(&self, hash_type: &T) -> Option<String> {
169 self.version_files()
170 .next()?
171 .lookup()
172 .hash_find(hash_type.to_string())
173 }
174
175 pub fn sha256(&self) -> Option<String> { self.hash("sha256") }
178
179 pub fn sha512(&self) -> Option<String> { self.hash("sha512") }
182
183 pub fn uris(&self) -> impl Iterator<Item = String> + 'a {
185 self.version_files().filter_map(|v| {
186 let pkg_file = v.package_file();
187 if !pkg_file.is_downloadable() {
188 return None;
189 }
190 Some(pkg_file.index_file().archive_uri(&v.lookup().filename()))
191 })
192 }
193
194 pub fn set_candidate(&self) { self.cache.depcache().set_candidate_version(self); }
196
197 pub fn priority(&self) -> i32 { self.cache.priority(self) }
199}
200
201impl PartialEq for Version<'_> {
203 fn eq(&self, other: &Self) -> bool {
204 matches!(
205 cmp_versions(self.version(), other.version()),
206 Ordering::Equal
207 )
208 }
209}
210
211impl Ord for Version<'_> {
212 fn cmp(&self, other: &Self) -> Ordering { cmp_versions(self.version(), other.version()) }
213}
214
215impl PartialOrd for Version<'_> {
216 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
217}
218
219impl fmt::Display for Version<'_> {
220 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221 write!(f, "{}", self.version())?;
222 Ok(())
223 }
224}
225
226impl fmt::Debug for Version<'_> {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 let parent = self.parent();
229 f.debug_struct("Version")
230 .field("pkg", &parent.name())
231 .field("arch", &self.arch())
232 .field("version", &self.version())
233 .field(
234 "is_candidate",
235 &parent.candidate().is_some_and(|cand| self == &cand),
236 )
237 .field("is_installed", &self.is_installed())
238 .finish_non_exhaustive()
239 }
240}
241
242#[cxx::bridge]
243pub(crate) mod raw {
244 impl CxxVector<VerIterator> {}
245 unsafe extern "C++" {
246 include!("rust-apt/apt-pkg-c/package.h");
247
248 type VerIterator;
249
250 type PkgIterator = crate::iterators::PkgIterator;
251 type PrvIterator = crate::iterators::PrvIterator;
252 type DepIterator = crate::iterators::DepIterator;
253 type DescIterator = crate::iterators::DescIterator;
254 type VerFileIterator = crate::iterators::VerFileIterator;
255
256 pub fn version(self: &VerIterator) -> &str;
258
259 pub fn arch(self: &VerIterator) -> &str;
261
262 unsafe fn parent_pkg(self: &VerIterator) -> UniquePtr<PkgIterator>;
268
269 pub fn section(self: &VerIterator) -> Result<&str>;
271
272 pub fn priority_str(self: &VerIterator) -> Result<&str>;
274
275 pub fn size(self: &VerIterator) -> u64;
277
278 pub fn installed_size(self: &VerIterator) -> u64;
280
281 pub fn multi_arch(self: &VerIterator) -> u8;
283
284 pub fn multi_arch_type(self: &VerIterator) -> &str;
287
288 #[cxx_name = "Downloadable"]
290 pub fn is_downloadable(self: &VerIterator) -> bool;
291
292 pub fn is_installed(self: &VerIterator) -> bool;
294
295 pub fn source_name(self: &VerIterator) -> &str;
297
298 pub fn source_version(self: &VerIterator) -> &str;
301
302 unsafe fn provides(self: &VerIterator) -> UniquePtr<PrvIterator>;
313
314 unsafe fn depends(self: &VerIterator) -> UniquePtr<DepIterator>;
325
326 unsafe fn version_files(self: &VerIterator) -> UniquePtr<VerFileIterator>;
338
339 unsafe fn translated_desc(self: &VerIterator) -> UniquePtr<DescIterator>;
350
351 #[cxx_name = "Index"]
352 pub fn index(self: &VerIterator) -> u64;
353 unsafe fn unique(self: &VerIterator) -> UniquePtr<VerIterator>;
359 pub fn raw_next(self: Pin<&mut VerIterator>);
360 pub fn end(self: &VerIterator) -> bool;
361 }
362}