1use std::cmp;
2use std::ffi;
3use std::marker::PhantomData;
4use std::sync::MutexGuard;
5
6use crate::citer::CIterator;
7use crate::citer::RawIterator;
8use crate::raw;
9
10#[derive(Debug)]
13pub struct Cache {
14 ptr_mutex: &'static raw::CACHE_SINGLETON,
15}
16
17impl Cache {
18 pub fn get_singleton() -> Cache {
20 Cache {
21 ptr_mutex: raw::pkg_cache_get_singleton(),
22 }
23 }
24
25 pub fn reload(&mut self) {
32 self.ptr_mutex.lock().expect("poisoned mutex").re_up()
33 }
34
35 pub fn iter(&mut self) -> CIterator<PkgIterator> {
41 let lock = self.ptr_mutex.lock().expect("poisoned mutex");
42 unsafe {
43 let raw_iter = raw::pkg_cache_pkg_iter(lock.ptr);
44 PkgIterator::new(lock, raw_iter)
45 }
46 }
47
48 pub fn find_by_name(&mut self, name: &str) -> CIterator<PkgIterator> {
53 let lock = self.ptr_mutex.lock().expect("poisoned mutex");
54 unsafe {
55 let name = ffi::CString::new(name).unwrap();
56 let ptr = raw::pkg_cache_find_name(lock.ptr, name.as_ptr());
57 PkgIterator::new(lock, ptr)
58 }
59 }
60
61 pub fn find_by_name_arch(&mut self, name: &str, arch: &str) -> CIterator<PkgIterator> {
65 let lock = self.ptr_mutex.lock().expect("poisoned mutex");
66 unsafe {
67 let name = ffi::CString::new(name).unwrap();
68 let arch = ffi::CString::new(arch).unwrap();
69 let ptr = raw::pkg_cache_find_name_arch(lock.ptr, name.as_ptr(), arch.as_ptr());
70 PkgIterator::new(lock, ptr)
71 }
72 }
73
74 pub fn compare_versions(&self, left: &str, right: &str) -> cmp::Ordering {
89 unsafe {
90 let left = ffi::CString::new(left).unwrap();
91 let right = ffi::CString::new(right).unwrap();
92
93 let lock = self.ptr_mutex.lock().expect("poisoned mutex");
94 raw::pkg_cache_compare_versions(lock.ptr, left.as_ptr(), right.as_ptr()).cmp(&0)
95 }
96 }
97}
98
99#[derive(Debug)]
101pub struct PkgIterator<'c> {
102 cache: MutexGuard<'c, raw::CacheHolder>,
103 ptr: raw::PPkgIterator,
104}
105
106impl<'c> PkgIterator<'c> {
107 fn new(cache: MutexGuard<'c, raw::CacheHolder>, ptr: raw::PCache) -> CIterator<Self> {
108 CIterator {
109 first: true,
110 raw: PkgIterator { cache, ptr },
111 }
112 }
113}
114
115pub struct PkgView<'c> {
118 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
119 ptr: raw::PPkgIterator,
120}
121
122impl<'c> RawIterator for PkgIterator<'c> {
123 type View = PkgView<'c>;
124
125 fn is_end(&self) -> bool {
126 unsafe { raw::pkg_iter_end(self.ptr) }
127 }
128
129 fn next(&mut self) {
130 unsafe { raw::pkg_iter_next(self.ptr) }
131 }
132
133 fn as_view(&self) -> Self::View {
134 assert!(!self.is_end());
135
136 PkgView {
137 ptr: self.ptr,
138 cache: PhantomData,
139 }
140 }
141
142 fn release(&mut self) {
143 unsafe { raw::pkg_iter_release(self.ptr) }
144 }
145}
146
147impl<'c> PkgView<'c> {
149 pub fn name(&self) -> String {
150 unsafe {
151 make_owned_ascii_string(raw::pkg_iter_name(self.ptr))
152 .expect("packages always have names")
153 }
154 }
155
156 pub fn arch(&self) -> String {
157 unsafe {
158 make_owned_ascii_string(raw::pkg_iter_arch(self.ptr))
159 .expect("packages always have architectures")
160 }
161 }
162
163 pub fn current_version(&self) -> Option<String> {
164 unsafe { make_owned_ascii_string(raw::pkg_iter_current_version(self.ptr)) }
165 }
166
167 pub fn candidate_version(&self) -> Option<String> {
168 unsafe { make_owned_ascii_string(raw::pkg_iter_candidate_version(self.ptr)) }
169 }
170
171 pub fn versions(&self) -> CIterator<VerIterator> {
172 CIterator {
173 first: true,
174 raw: VerIterator {
175 cache: PhantomData,
176 ptr: unsafe { raw::pkg_iter_ver_iter(self.ptr) },
177 },
178 }
179 }
180}
181
182pub struct SinglePkgView<'c> {
185 view: PkgView<'c>,
186}
187
188impl<'c> std::ops::Deref for SinglePkgView<'c> {
189 type Target = PkgView<'c>;
190
191 fn deref(&self) -> &Self::Target {
192 &self.view
193 }
194}
195
196impl<'c> Drop for SinglePkgView<'c> {
197 fn drop(&mut self) {
198 unsafe {
199 raw::pkg_iter_release(self.view.ptr);
200 }
201 }
202}
203
204pub struct VerIterator<'c> {
206 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
207 ptr: raw::PVerIterator,
208}
209
210pub struct VerView<'c> {
211 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
212 ptr: raw::PVerIterator,
213}
214
215impl<'c> RawIterator for VerIterator<'c> {
216 type View = VerView<'c>;
217
218 fn is_end(&self) -> bool {
219 unsafe { raw::ver_iter_end(self.ptr) }
220 }
221
222 fn next(&mut self) {
223 unsafe { raw::ver_iter_next(self.ptr) }
224 }
225
226 fn as_view(&self) -> Self::View {
227 assert!(!self.is_end());
228
229 VerView {
230 ptr: self.ptr,
231 cache: self.cache,
232 }
233 }
234
235 fn release(&mut self) {
236 unsafe { raw::ver_iter_release(self.ptr) }
237 }
238}
239
240impl<'c> VerView<'c> {
242 pub fn version(&self) -> String {
243 unsafe {
244 make_owned_ascii_string(raw::ver_iter_version(self.ptr))
245 .expect("versions always have a version")
246 }
247 }
248
249 pub fn arch(&self) -> String {
250 unsafe {
251 make_owned_ascii_string(raw::ver_iter_arch(self.ptr))
252 .expect("versions always have an arch")
253 }
254 }
255
256 pub fn section(&self) -> Option<String> {
257 unsafe { make_owned_ascii_string(raw::ver_iter_section(self.ptr)) }
258 }
259
260 pub fn priority_type(&self) -> Option<String> {
261 unsafe { make_owned_ascii_string(raw::ver_iter_priority_type(self.ptr)) }
262 }
263
264 #[cfg(not(feature = "ye-olde-apt"))]
265 pub fn source_package(&self) -> String {
266 unsafe {
267 make_owned_ascii_string(raw::ver_iter_source_package(self.ptr))
268 .expect("versions always have a source package")
269 }
270 }
271
272 #[cfg(not(feature = "ye-olde-apt"))]
273 pub fn source_version(&self) -> String {
274 unsafe {
275 make_owned_ascii_string(raw::ver_iter_source_version(self.ptr))
276 .expect("versions always have a source_version")
277 }
278 }
279
280 #[cfg(not(feature = "ye-olde-apt"))]
281 pub fn priority(&self) -> i32 {
282 unsafe { raw::ver_iter_priority(self.ptr) }
283 }
284
285 pub fn origin_iter(&self) -> CIterator<VerFileIterator> {
286 CIterator {
287 first: true,
288 raw: VerFileIterator {
289 cache: PhantomData,
290 ptr: unsafe { raw::ver_iter_ver_file_iter(self.ptr) },
291 },
292 }
293 }
294
295 pub fn dep_iter(&self) -> CIterator<DepIterator> {
296 CIterator {
297 first: true,
298 raw: DepIterator {
299 cache: PhantomData,
300 ptr: unsafe { raw::ver_iter_dep_iter(self.ptr) },
301 },
302 }
303 }
304}
305
306pub struct DepIterator<'c> {
308 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
309 ptr: raw::PDepIterator,
310}
311
312pub struct DepView<'c> {
313 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
314 ptr: raw::PDepIterator,
315}
316
317impl<'c> RawIterator for DepIterator<'c> {
318 type View = DepView<'c>;
319
320 fn is_end(&self) -> bool {
321 unsafe { raw::dep_iter_end(self.ptr) }
322 }
323
324 fn next(&mut self) {
325 unsafe { raw::dep_iter_next(self.ptr) }
326 }
327
328 fn as_view(&self) -> Self::View {
329 assert!(!self.is_end());
330
331 DepView {
332 ptr: self.ptr,
333 cache: self.cache,
334 }
335 }
336
337 fn release(&mut self) {
338 unsafe { raw::dep_iter_release(self.ptr) }
339 }
340}
341
342impl<'c> DepView<'c> {
344 pub fn target_pkg(&self) -> SinglePkgView {
345 let ptr = unsafe { raw::dep_iter_target_pkg(self.ptr) };
346 SinglePkgView {
347 view: PkgView {
348 cache: self.cache,
349 ptr,
350 },
351 }
352 }
353
354 pub fn target_ver(&self) -> String {
355 unsafe {
356 make_owned_ascii_string(raw::dep_iter_target_ver(self.ptr))
357 .expect("dependency always has target version")
358 }
359 }
360
361 pub fn comp_type(&self) -> String {
362 unsafe {
363 make_owned_ascii_string(raw::dep_iter_comp_type(self.ptr))
364 .expect("dependency always has comp type")
365 }
366 }
367
368 pub fn dep_type(&self) -> String {
369 unsafe {
370 make_owned_ascii_string(raw::dep_iter_dep_type(self.ptr))
371 .expect("dependency always has dep type")
372 }
373 }
374}
375
376pub struct VerFileIterator<'c> {
378 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
379 ptr: raw::PVerFileIterator,
380}
381
382pub struct VerFileView<'c> {
385 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
386 ptr: raw::PVerFileIterator,
387 parser: raw::PVerFileParser,
388}
389
390impl<'c> RawIterator for VerFileIterator<'c> {
391 type View = VerFileView<'c>;
392
393 fn is_end(&self) -> bool {
394 unsafe { raw::ver_file_iter_end(self.ptr) }
395 }
396
397 fn next(&mut self) {
398 unsafe { raw::ver_file_iter_next(self.ptr) }
399 }
400
401 fn as_view(&self) -> Self::View {
402 assert!(!self.is_end());
403
404 let parser = unsafe { raw::ver_file_iter_get_parser(self.ptr) };
405
406 VerFileView {
407 ptr: self.ptr,
408 cache: self.cache,
409 parser,
410 }
411 }
412
413 fn release(&mut self) {
414 unsafe { raw::ver_file_iter_release(self.ptr) }
415 }
416}
417
418impl<'c> VerFileView<'c> {
419 pub fn file(&self) -> CIterator<PkgFileIterator> {
420 CIterator {
421 first: true,
422 raw: PkgFileIterator {
423 cache: PhantomData,
424 ptr: unsafe { raw::ver_file_iter_pkg_file_iter(self.ptr) },
425 },
426 }
427 }
428
429 pub fn short_desc(&self) -> Option<String> {
430 unsafe { make_owned_ascii_string(raw::ver_file_parser_short_desc(self.parser)) }
431 }
432
433 pub fn long_desc(&self) -> Option<String> {
434 unsafe { make_owned_ascii_string(raw::ver_file_parser_long_desc(self.parser)) }
435 }
436
437 pub fn maintainer(&self) -> Option<String> {
438 unsafe { make_owned_ascii_string(raw::ver_file_parser_maintainer(self.parser)) }
439 }
440
441 pub fn homepage(&self) -> Option<String> {
442 unsafe { make_owned_ascii_string(raw::ver_file_parser_homepage(self.parser)) }
443 }
444}
445
446pub struct PkgFileIterator<'c> {
448 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
449 ptr: raw::PPkgFileIterator,
450}
451
452pub struct PkgFileView<'c> {
455 cache: PhantomData<&'c MutexGuard<'c, raw::CacheHolder>>,
456 ptr: raw::PPkgFileIterator,
457}
458
459impl<'c> RawIterator for PkgFileIterator<'c> {
460 type View = PkgFileView<'c>;
461
462 fn is_end(&self) -> bool {
463 unsafe { raw::pkg_file_iter_end(self.ptr) }
464 }
465
466 fn next(&mut self) {
467 unsafe { raw::pkg_file_iter_next(self.ptr) }
468 }
469
470 fn as_view(&self) -> Self::View {
471 assert!(!self.is_end());
472
473 PkgFileView {
474 ptr: self.ptr,
475 cache: self.cache,
476 }
477 }
478
479 fn release(&mut self) {
480 unsafe { raw::pkg_file_iter_release(self.ptr) }
481 }
482}
483
484impl<'c> PkgFileView<'c> {
485 pub fn file_name(&self) -> String {
486 unsafe {
487 make_owned_ascii_string(raw::pkg_file_iter_file_name(self.ptr))
488 .expect("package file always has a file name")
489 }
490 }
491 pub fn archive(&self) -> String {
492 unsafe {
493 make_owned_ascii_string(raw::pkg_file_iter_archive(self.ptr))
494 .expect("package file always has an archive")
495 }
496 }
497 pub fn version(&self) -> Option<String> {
498 unsafe { make_owned_ascii_string(raw::pkg_file_iter_version(self.ptr)) }
499 }
500 pub fn origin(&self) -> Option<String> {
501 unsafe { make_owned_ascii_string(raw::pkg_file_iter_origin(self.ptr)) }
502 }
503 pub fn codename(&self) -> Option<String> {
504 unsafe { make_owned_ascii_string(raw::pkg_file_iter_codename(self.ptr)) }
505 }
506 pub fn label(&self) -> Option<String> {
507 unsafe { make_owned_ascii_string(raw::pkg_file_iter_label(self.ptr)) }
508 }
509 pub fn site(&self) -> Option<String> {
510 unsafe { make_owned_ascii_string(raw::pkg_file_iter_site(self.ptr)) }
511 }
512 pub fn component(&self) -> String {
513 unsafe {
514 make_owned_ascii_string(raw::pkg_file_iter_component(self.ptr))
515 .expect("package file always has a component")
516 }
517 }
518 pub fn architecture(&self) -> Option<String> {
519 unsafe { make_owned_ascii_string(raw::pkg_file_iter_architecture(self.ptr)) }
520 }
521 pub fn index_type(&self) -> String {
522 unsafe {
523 make_owned_ascii_string(raw::pkg_file_iter_index_type(self.ptr))
524 .expect("package file always has a index_type")
525 }
526 }
527}
528
529unsafe fn make_owned_ascii_string(ptr: *const libc::c_char) -> Option<String> {
530 if ptr.is_null() {
531 None
532 } else {
533 Some(
534 ffi::CStr::from_ptr(ptr)
535 .to_str()
536 .expect("value should always be low-ascii")
537 .to_string(),
538 )
539 }
540}