1use crate::{
2 free, Alpm, Backup, Conflict, Db, DbMut, Dep, DepMissing, Depend, DependMissing, FileConflict,
3 Group, LoadedPackage, OwnedConflict, OwnedFileConflict, Package, Pkg, LIBRARY, Library
4};
5
6use std::ffi::{c_void, CStr};
7use std::fmt;
8use std::iter::{ExactSizeIterator, Iterator};
9use std::marker::PhantomData;
10use std::mem::ManuallyDrop;
11use std::os::raw::c_char;
12use std::ptr;
13
14use alpm_sys_ll::*;
15
16extern "C" {
17 fn strndup(cs: *const c_char, n: usize) -> *mut c_char;
18}
19
20pub unsafe trait IntoAlpmListItem<'a, 'b> {
21 type Borrow: fmt::Debug;
22 #[doc(hidden)]
23 unsafe fn ptr_into_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self;
24 #[doc(hidden)]
25 unsafe fn ptr_as_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow;
26}
27
28pub unsafe trait AsAlpmListItemPtr<'a> {
29 type Output;
30 const FREE: Option<unsafe extern "C" fn(_ptr: *mut c_void)> = None;
31 fn as_ptr(&self) -> *mut c_void;
32}
33
34pub trait Bool {
35 const DROP: bool;
36}
37
38pub unsafe trait Push<'a>: AsAlpmListItemPtr<'a> {}
39
40pub struct True;
41pub struct False;
42
43impl Bool for True {
44 const DROP: bool = true;
45}
46
47impl Bool for False {
48 const DROP: bool = false;
49}
50
51pub struct RawAlpmList<'a, T, D>
52where
53 D: Bool,
54 T: AsAlpmListItemPtr<'a>,
55{
56 list: *mut alpm_list_t,
57 _marker1: PhantomData<&'a T>,
58 _marker2: PhantomData<D>,
59}
60
61impl<'a, T, D> RawAlpmList<'a, T, D>
62where
63 D: Bool,
64 T: AsAlpmListItemPtr<'a>,
65{
66 pub fn list(&self) -> *mut alpm_list_t {
67 self.list
68 }
69}
70
71impl<'a, T, D> Drop for RawAlpmList<'a, T, D>
72where
73 D: Bool,
74 T: AsAlpmListItemPtr<'a>,
75{
76 fn drop(&mut self) {
77 if D::DROP {
78 if let Some(free) = T::FREE {
79 unsafe { LIBRARY.force_load().alpm_list_free_inner(self.list, Some(free)) }
80 }
81 unsafe { LIBRARY.force_load().alpm_list_free(self.list) };
82 }
83 }
84}
85
86pub trait IntoRawAlpmList<'a, T>
87where
88 T: AsAlpmListItemPtr<'a>,
89{
90 #[doc(hidden)]
91 type Drop: Bool;
92 #[doc(hidden)]
93 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, T, Self::Drop>;
94}
95
96impl<'a> IntoRawAlpmList<'a, Pkg<'a>> for AlpmList<'a, LoadedPackage<'a>> {
97 type Drop = False;
98 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, Pkg<'a>, Self::Drop> {
99 RawAlpmList {
100 list: self.list,
101 _marker1: PhantomData,
102 _marker2: PhantomData,
103 }
104 }
105}
106
107impl<'a> IntoRawAlpmList<'a, Pkg<'a>> for AlpmList<'a, Package<'a>> {
108 type Drop = False;
109 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, Pkg<'a>, Self::Drop> {
110 RawAlpmList {
111 list: self.list,
112 _marker1: PhantomData,
113 _marker2: PhantomData,
114 }
115 }
116}
117
118impl<'a, T> IntoRawAlpmList<'a, T> for AlpmList<'a, T>
119where
120 T: AsAlpmListItemPtr<'a>,
121{
122 type Drop = False;
123 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, T, Self::Drop> {
124 RawAlpmList {
125 list: self.list,
126 _marker1: PhantomData,
127 _marker2: PhantomData,
128 }
129 }
130}
131
132impl<'a, T> IntoRawAlpmList<'a, T> for &AlpmListMut<'a, T>
133where
134 for<'b> T: IntoAlpmListItem<'a, 'b> + AsAlpmListItemPtr<'a>,
135{
136 type Drop = False;
137 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, T, Self::Drop> {
138 RawAlpmList {
139 list: self.list.list,
140 _marker1: PhantomData,
141 _marker2: PhantomData,
142 }
143 }
144}
145
146impl<'a, T, D: Bool> IntoRawAlpmList<'a, T> for RawAlpmList<'a, T, D>
147where
148 T: AsAlpmListItemPtr<'a>,
149{
150 type Drop = D;
151 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, T, Self::Drop> {
152 self
153 }
154}
155
156impl<'a, T, I> IntoRawAlpmList<'a, T::Output> for I
157where
158 I: Iterator<Item = T>,
159 T: AsAlpmListItemPtr<'a>,
160 T::Output: AsAlpmListItemPtr<'a>,
161{
162 type Drop = True;
163 unsafe fn into_raw_alpm_list(self) -> RawAlpmList<'a, T::Output, Self::Drop> {
164 let mut list = ptr::null_mut();
165
166 for item in self {
167 list = LIBRARY.force_load().alpm_list_add(list, item.as_ptr());
168 if T::FREE.is_none() {
169 std::mem::forget(item);
170 }
171 }
172
173 RawAlpmList {
174 list,
175 _marker1: PhantomData,
176 _marker2: PhantomData,
177 }
178 }
179}
180
181pub struct AlpmList<'a, T> {
182 pub(crate) handle: &'a Alpm,
183 pub(crate) list: *mut alpm_list_t,
184 pub(crate) _marker: PhantomData<T>,
185}
186
187impl<'a, T> fmt::Debug for AlpmList<'a, T>
188where
189 for<'b> T: IntoAlpmListItem<'a, 'b>,
190{
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 f.write_str("AlpmList ")?;
193 f.debug_list().entries(self).finish()
194 }
195}
196
197impl<'a, T> Clone for AlpmList<'a, T> {
198 fn clone(&self) -> Self {
199 AlpmList {
200 handle: self.handle,
201 list: self.list,
202 _marker: self._marker,
203 }
204 }
205}
206
207impl<'a, T> Copy for AlpmList<'a, T> {}
208
209pub struct AlpmListMut<'a, T>
210where
211 for<'b> T: IntoAlpmListItem<'a, 'b>,
212{
213 list: AlpmList<'a, T>,
214}
215
216impl<'a, T> fmt::Debug for AlpmListMut<'a, T>
217where
218 for<'b> T: IntoAlpmListItem<'a, 'b>,
219{
220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221 fmt::Debug::fmt(&self.as_list(), f)
222 }
223}
224
225impl<'a, T> std::ops::Deref for AlpmListMut<'a, T>
226where
227 for<'b> T: IntoAlpmListItem<'a, 'b>,
228{
229 type Target = AlpmList<'a, T>;
230
231 fn deref(&self) -> &Self::Target {
232 &self.list
233 }
234}
235
236impl<'a, T> Drop for AlpmListMut<'a, T>
237where
238 for<'b> T: IntoAlpmListItem<'a, 'b>,
239{
240 fn drop(&mut self) {
241 let list = self.list.list;
242 let mut curr = list;
243
244 while !curr.is_null() {
245 let item = unsafe { T::ptr_into_alpm_list_item(self.handle, (*curr).data) };
246 drop(item);
247 curr = unsafe { (*curr).next };
248 }
249
250 unsafe { LIBRARY.force_load().alpm_list_free(list) }
251 }
252}
253
254impl<'a, 'b, T> AlpmList<'a, T>
255where
256 T: IntoAlpmListItem<'a, 'b>,
257{
258 pub fn len(&self) -> usize {
259 unsafe { LIBRARY.force_load().alpm_list_count(self.list) }
260 }
261
262 pub fn is_empty(&self) -> bool {
263 self.list.is_null()
264 }
265
266 pub fn first(&'b self) -> Option<T::Borrow> {
267 if self.is_empty() {
268 None
269 } else {
270 unsafe { Some(T::ptr_as_alpm_list_item(self.handle, (*self.list).data)) }
271 }
272 }
273
274 pub fn last(&'b self) -> Option<T::Borrow> {
275 let item = unsafe { LIBRARY.force_load().alpm_list_last(self.list) };
276 if item.is_null() {
277 None
278 } else {
279 unsafe { Some(T::ptr_as_alpm_list_item(self.handle, (*item).data)) }
280 }
281 }
282
283 pub fn iter(&'b self) -> Iter<'a, 'b, T> {
284 self.into_iter()
285 }
286}
287
288impl<'a> AlpmList<'a, String> {
289 pub fn as_str<'b>(&'b self) -> AlpmList<'a, &'b str> {
290 unsafe { AlpmList::from_parts(self.handle, self.list) }
291 }
292}
293
294impl<'a, T> AlpmList<'a, T>
295where
296 for<'b> T: IntoAlpmListItem<'a, 'b>,
297{
298 #[allow(clippy::wrong_self_convention)]
299 pub fn to_list_mut(&self) -> AlpmListMut<'a, T> {
300 let list = unsafe { LIBRARY.force_load().alpm_list_copy(self.list) };
301 AlpmListMut {
302 list: unsafe { AlpmList::from_parts(self.handle, list) },
303 }
304 }
305}
306
307impl<'a, T> AlpmListMut<'a, T>
308where
309 for<'b> T: IntoAlpmListItem<'a, 'b> + Push<'a> + AsAlpmListItemPtr<'a>,
310{
311 pub fn push(&mut self, t: T) {
312 unsafe { self.list.list = LIBRARY.force_load().alpm_list_add(self.list.list, t.as_ptr()) };
313 if T::FREE.is_none() {
314 std::mem::forget(t);
315 }
316 }
317}
318
319impl<'a, T> Extend<T> for AlpmListMut<'a, T>
320where
321 for<'b> T: IntoAlpmListItem<'a, 'b> + Push<'a>,
322{
323 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
324 for item in iter {
325 self.push(item);
326 }
327 }
328}
329
330impl<'a> AlpmListMut<'a, String> {
331 pub fn push_str(&mut self, s: &str) {
332 let s = unsafe { strndup(s.as_bytes().as_ptr() as _, s.len()) };
333 unsafe { self.list.list = LIBRARY.force_load().alpm_list_add(self.list.list, s as *mut c_void) };
334 }
335}
336
337impl<'a, T> AlpmListMut<'a, T>
338where
339 for<'b> T: IntoAlpmListItem<'a, 'b>,
340{
341 pub fn retain<F>(&mut self, mut f: F)
342 where
343 F: FnMut(&T) -> bool,
344 {
345 let mut list = self.list.list;
346 let mut curr = list;
347
348 while !curr.is_null() {
349 let item = unsafe { T::ptr_into_alpm_list_item(self.handle, (*curr).data) };
350 let next = unsafe { (*curr).next };
351 if !f(&item) {
352 drop(item);
353 unsafe { list = LIBRARY.force_load().alpm_list_remove_item(list, curr) };
354 unsafe { free(curr as _) };
355 } else {
356 std::mem::forget(item);
357 }
358 curr = next;
359 }
360
361 self.list.list = list;
362 }
363
364 pub fn remove(&mut self, n: usize) -> Option<T> {
365 if n >= self.len() {
366 return None;
367 }
368
369 let item = unsafe { LIBRARY.force_load().alpm_list_nth(self.list.list, n) };
370 unsafe { self.list.list = LIBRARY.force_load().alpm_list_remove_item(self.list.list, item) };
371 let ret = unsafe {
372 Some(T::ptr_into_alpm_list_item(
373 self.handle,
374 (*self.list.list).data,
375 ))
376 };
377 unsafe { free(item as _) };
378 ret
379 }
380
381 pub fn remove_list(&mut self, n: usize) -> AlpmListMut<'a, T> {
382 if n >= self.len() {
383 return AlpmListMut::new(self.handle);
384 }
385
386 let item = unsafe { LIBRARY.force_load().alpm_list_nth(self.list.list, n) };
387 self.list.list = unsafe { LIBRARY.force_load().alpm_list_remove_item(self.list.list, item) };
388 unsafe { (*item).next = ptr::null_mut() };
389 unsafe { (*item).prev = ptr::null_mut() };
390 unsafe { AlpmListMut::from_parts(self.handle, item) }
391 }
392
393 pub fn as_list(&self) -> AlpmList<'a, T> {
394 self.list
395 }
396}
397
398impl<'a, T> IntoIterator for AlpmListMut<'a, T>
399where
400 for<'b> T: IntoAlpmListItem<'a, 'b>,
401{
402 type Item = T;
403 type IntoIter = IntoIterMut<'a, T>;
404
405 fn into_iter(self) -> Self::IntoIter {
406 IntoIterMut {
407 current: self.list.list,
408 list: ManuallyDrop::new(self),
409 }
410 }
411}
412
413impl<'a, 'b, T> IntoIterator for &'b AlpmListMut<'a, T>
414where
415 for<'c> T: IntoAlpmListItem<'a, 'c>,
416{
417 type Item = <T as IntoAlpmListItem<'a, 'b>>::Borrow;
418 type IntoIter = Iter<'a, 'b, T>;
419
420 fn into_iter(self) -> Self::IntoIter {
421 self.iter()
422 }
423}
424
425impl<'a, 'b, T> IntoIterator for &'b AlpmList<'a, T>
426where
427 T: IntoAlpmListItem<'a, 'b>,
428{
429 type Item = T::Borrow;
430 type IntoIter = Iter<'a, 'b, T>;
431
432 fn into_iter(self) -> Self::IntoIter {
433 Iter {
434 current: self.list,
435 list: self,
436 }
437 }
438}
439
440impl<'a, T> IntoIterator for AlpmList<'a, T>
441where
442 T: IntoAlpmListItem<'a, 'a>,
443{
444 type Item = T::Borrow;
445 type IntoIter = IntoIter<'a, T>;
446
447 fn into_iter(self) -> Self::IntoIter {
448 IntoIter {
449 current: self.list,
450 list: self,
451 }
452 }
453}
454
455#[derive(Copy, Clone)]
456pub struct Iter<'a, 'b, T>
457where
458 T: IntoAlpmListItem<'a, 'b>,
459{
460 list: &'b AlpmList<'a, T>,
461 current: *mut alpm_list_t,
462}
463
464impl<'a, 'b, T> fmt::Debug for Iter<'a, 'b, T>
465where
466 for<'c> T: IntoAlpmListItem<'a, 'c>,
467{
468 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
469 f.debug_struct("Iter").field("list", self.list).finish()
470 }
471}
472
473#[derive(Copy, Clone)]
474pub struct IntoIter<'a, T>
475where
476 T: IntoAlpmListItem<'a, 'a>,
477{
478 list: AlpmList<'a, T>,
479 current: *mut alpm_list_t,
480}
481
482impl<'a, T> fmt::Debug for IntoIter<'a, T>
483where
484 for<'b> T: IntoAlpmListItem<'a, 'b>,
485{
486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487 f.debug_struct("Iter").field("list", &self.list).finish()
488 }
489}
490
491impl<'a, 'b, T> Iter<'a, 'b, T>
492where
493 T: IntoAlpmListItem<'a, 'b>,
494{
495 fn next_data(&mut self) -> Option<*mut c_void> {
496 if self.current.is_null() {
497 None
498 } else {
499 let data = unsafe { (*(self.current)).data };
500 self.current = unsafe { LIBRARY.force_load().alpm_list_next(self.current) };
501
502 Some(data)
503 }
504 }
505}
506
507pub struct IntoIterMut<'a, T>
508where
509 for<'b> T: IntoAlpmListItem<'a, 'b>,
510{
511 list: ManuallyDrop<AlpmListMut<'a, T>>,
512 current: *mut alpm_list_t,
513}
514
515impl<'a, T> fmt::Debug for IntoIterMut<'a, T>
516where
517 for<'b> T: IntoAlpmListItem<'a, 'b>,
518{
519 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520 f.debug_struct("Iter").field("list", &self.list).finish()
521 }
522}
523
524impl<'a, T> Drop for IntoIterMut<'a, T>
525where
526 for<'b> T: IntoAlpmListItem<'a, 'b>,
527{
528 fn drop(&mut self) {
529 unsafe { AlpmListMut::<T>::from_parts(self.list.handle, self.current) };
530 }
531}
532
533impl<'a, T> ExactSizeIterator for IntoIterMut<'a, T> where for<'b> T: IntoAlpmListItem<'a, 'b> {}
534impl<'a, T> ExactSizeIterator for IntoIter<'a, T> where for<'b> T: IntoAlpmListItem<'a, 'b> {}
535impl<'a, 'b, T> ExactSizeIterator for Iter<'a, 'b, T> where T: IntoAlpmListItem<'a, 'b> {}
536
537impl<'a, T> Iterator for IntoIterMut<'a, T>
538where
539 for<'b> T: IntoAlpmListItem<'a, 'b>,
540{
541 type Item = T;
542 fn next(&mut self) -> Option<Self::Item> {
543 let data = self.next_data();
544
545 match data {
546 Some(data) => unsafe { Some(T::ptr_into_alpm_list_item(self.list.handle, data)) },
547 None => None,
548 }
549 }
550
551 fn size_hint(&self) -> (usize, Option<usize>) {
552 let size = unsafe { LIBRARY.force_load().alpm_list_count(self.list.list.list) };
553 (size, Some(size))
554 }
555}
556
557impl<'a, 'b, T> Iterator for Iter<'a, 'b, T>
558where
559 T: IntoAlpmListItem<'a, 'b>,
560{
561 type Item = T::Borrow;
562 fn next(&mut self) -> Option<Self::Item> {
563 let data = self.next_data();
564
565 match data {
566 Some(data) => unsafe { Some(T::ptr_as_alpm_list_item(self.list.handle, data)) },
567 None => None,
568 }
569 }
570
571 fn size_hint(&self) -> (usize, Option<usize>) {
572 let size = unsafe { LIBRARY.force_load().alpm_list_count(self.list.list) };
573 (size, Some(size))
574 }
575}
576
577impl<'a, T> Iterator for IntoIter<'a, T>
578where
579 T: IntoAlpmListItem<'a, 'a>,
580{
581 type Item = T::Borrow;
582 fn next(&mut self) -> Option<Self::Item> {
583 let data = self.next_data();
584
585 match data {
586 Some(data) => unsafe { Some(T::ptr_as_alpm_list_item(self.list.handle, data)) },
587 None => None,
588 }
589 }
590
591 fn size_hint(&self) -> (usize, Option<usize>) {
592 let size = unsafe { LIBRARY.force_load().alpm_list_count(self.list.list) };
593 (size, Some(size))
594 }
595}
596
597impl<'a, T> IntoIter<'a, T>
598where
599 T: IntoAlpmListItem<'a, 'a>,
600{
601 fn next_data(&mut self) -> Option<*mut c_void> {
602 if self.current.is_null() {
603 None
604 } else {
605 let data = unsafe { (*(self.current)).data };
606 self.current = unsafe { LIBRARY.force_load().alpm_list_next(self.current) };
607
608 Some(data)
609 }
610 }
611}
612
613impl<'a, T> IntoIterMut<'a, T>
614where
615 for<'b> T: IntoAlpmListItem<'a, 'b>,
616{
617 fn next_data(&mut self) -> Option<*mut c_void> {
618 if self.current.is_null() {
619 None
620 } else {
621 let data = unsafe { (*(self.current)).data };
622 self.current = unsafe { LIBRARY.force_load().alpm_list_next(self.current) };
623
624 Some(data)
625 }
626 }
627}
628
629impl<'a, T> AlpmList<'a, T> {
630 pub(crate) unsafe fn from_parts(handle: &'a Alpm, list: *mut alpm_list_t) -> AlpmList<'a, T> {
631 AlpmList {
632 handle,
633 list,
634 _marker: PhantomData,
635 }
636 }
637}
638
639impl<'a, T> AlpmListMut<'a, T>
640where
641 for<'b> T: IntoAlpmListItem<'a, 'b>,
642{
643 pub fn new(handle: &'a Alpm) -> AlpmListMut<'a, T> {
644 AlpmListMut {
645 list: unsafe { AlpmList::from_parts(handle, ptr::null_mut()) },
646 }
647 }
648
649 pub(crate) unsafe fn from_parts(
650 handle: &'a Alpm,
651 list: *mut alpm_list_t,
652 ) -> AlpmListMut<'a, T> {
653 AlpmListMut {
654 list: AlpmList::from_parts(handle, list),
655 }
656 }
657}
658
659unsafe impl<'a> AsAlpmListItemPtr<'a> for Pkg<'a> {
660 type Output = Pkg<'a>;
661
662 fn as_ptr(&self) -> *mut c_void {
663 (*self).as_ptr() as *mut c_void
664 }
665}
666
667unsafe impl<'a> AsAlpmListItemPtr<'a> for Package<'a> {
668 type Output = Package<'a>;
669
670 fn as_ptr(&self) -> *mut c_void {
671 self.pkg.as_ptr() as *mut c_void
672 }
673}
674
675unsafe impl<'a> AsAlpmListItemPtr<'a> for LoadedPackage<'a> {
676 type Output = Pkg<'a>;
677
678 fn as_ptr(&self) -> *mut c_void {
679 self.pkg.as_ptr() as *mut c_void
680 }
681}
682
683unsafe impl<'a> AsAlpmListItemPtr<'a> for Db<'a> {
684 type Output = Db<'a>;
685
686 fn as_ptr(&self) -> *mut c_void {
687 (*self).as_ptr() as *mut c_void
688 }
689}
690
691unsafe impl<'a> AsAlpmListItemPtr<'a> for Depend {
692 type Output = Dep<'a>;
693
694 fn as_ptr(&self) -> *mut c_void {
695 Dep::as_ptr(self) as *mut c_void
696 }
697}
698
699unsafe impl<'a, T: AsAlpmListItemPtr<'a>> AsAlpmListItemPtr<'a> for &T {
700 type Output = T::Output;
701
702 fn as_ptr(&self) -> *mut c_void {
703 (*self).as_ptr()
704 }
705}
706
707unsafe impl<'a> AsAlpmListItemPtr<'a> for Dep<'a> {
708 type Output = Dep<'a>;
709
710 fn as_ptr(&self) -> *mut c_void {
711 Dep::as_ptr(self) as *mut c_void
712 }
713}
714
715unsafe impl<'a> AsAlpmListItemPtr<'a> for String {
716 type Output = String;
717 const FREE: Option<unsafe extern "C" fn(_ptr: *mut c_void)> = Some(free);
718 fn as_ptr(&self) -> *mut c_void {
719 unsafe { strndup(self.as_bytes().as_ptr() as _, self.len()) as *mut c_void }
720 }
721}
722
723unsafe impl<'a> AsAlpmListItemPtr<'a> for &str {
724 type Output = String;
725 const FREE: Option<unsafe extern "C" fn(_ptr: *mut c_void)> = Some(free);
726
727 fn as_ptr(&self) -> *mut c_void {
728 unsafe { strndup(self.as_bytes().as_ptr() as _, self.len()) as *mut c_void }
729 }
730}
731
732unsafe impl<'a> Push<'a> for String {}
733unsafe impl<'a> Push<'a> for Pkg<'a> {}
734unsafe impl<'a> Push<'a> for Package<'a> {}
735unsafe impl<'a> Push<'a> for Db<'a> {}
736unsafe impl<'a> Push<'a> for Depend {}
737unsafe impl<'a> Push<'a> for Dep<'a> {}
738
739unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Package<'a> {
740 type Borrow = Self;
741 unsafe fn ptr_into_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self {
742 Package::new(handle, ptr as *mut alpm_pkg_t)
743 }
744 unsafe fn ptr_as_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
745 Package::new(handle, ptr as *mut alpm_pkg_t)
746 }
747}
748
749unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Group<'a> {
750 type Borrow = Self;
751 unsafe fn ptr_into_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self {
752 Group::new(handle, ptr as *mut alpm_group_t)
753 }
754 unsafe fn ptr_as_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
755 Group::new(handle, ptr as *mut alpm_group_t)
756 }
757}
758
759unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Depend {
760 type Borrow = Dep<'b>;
761 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
762 Depend::from_ptr(ptr as *mut alpm_depend_t)
763 }
764 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
765 Dep::from_ptr(ptr as *mut alpm_depend_t)
766 }
767}
768
769unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Dep<'a> {
770 type Borrow = Self;
771 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
772 Dep::from_ptr(ptr as *mut alpm_depend_t)
773 }
774
775 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
776 Dep::from_ptr(ptr as *mut alpm_depend_t)
777 }
778}
779
780unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Backup {
781 type Borrow = Self;
782 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
783 Backup::from_ptr(ptr as *mut alpm_backup_t)
784 }
785 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
786 Backup::from_ptr(ptr as *mut alpm_backup_t)
787 }
788}
789
790unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for OwnedFileConflict {
791 type Borrow = FileConflict<'b>;
792 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
793 OwnedFileConflict {
794 inner: FileConflict::from_ptr(ptr as *mut alpm_fileconflict_t),
795 }
796 }
797
798 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
799 FileConflict::from_ptr(ptr as *mut alpm_fileconflict_t)
800 }
801}
802
803unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for DependMissing {
804 type Borrow = DepMissing<'b>;
805 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
806 DependMissing {
807 inner: DepMissing::from_ptr(ptr as *mut alpm_depmissing_t),
808 }
809 }
810
811 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
812 DepMissing::from_ptr(ptr as *mut alpm_depmissing_t)
813 }
814}
815
816unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for OwnedConflict {
817 type Borrow = Conflict<'b>;
818 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
819 OwnedConflict::from_ptr(ptr as *mut alpm_conflict_t)
820 }
821 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
822 Conflict::from_ptr(ptr as *mut alpm_conflict_t)
823 }
824}
825
826unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Conflict<'a> {
827 type Borrow = Self;
828 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
829 Conflict::from_ptr(ptr as *mut alpm_conflict_t)
830 }
831 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
832 Conflict::from_ptr(ptr as *mut alpm_conflict_t)
833 }
834}
835
836unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for Db<'a> {
837 type Borrow = Self;
838 unsafe fn ptr_into_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self {
839 Db::new(handle, ptr as *mut alpm_db_t)
840 }
841 unsafe fn ptr_as_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
842 Db::new(handle, ptr as *mut alpm_db_t)
843 }
844}
845
846unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for DbMut<'a> {
847 type Borrow = Self;
848 unsafe fn ptr_into_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self {
849 DbMut {
850 inner: Db::new(handle, ptr as *mut alpm_db_t),
851 }
852 }
853 unsafe fn ptr_as_alpm_list_item(handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
854 DbMut {
855 inner: Db::new(handle, ptr as *mut alpm_db_t),
856 }
857 }
858}
859
860unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for &'a str {
861 type Borrow = Self;
862 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
863 let s = CStr::from_ptr(ptr as *mut c_char);
864 s.to_str().unwrap()
865 }
866 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
867 let s = CStr::from_ptr(ptr as *mut c_char);
868 s.to_str().unwrap()
869 }
870}
871
872unsafe impl<'a, 'b> IntoAlpmListItem<'a, 'b> for String {
873 type Borrow = &'b str;
874 unsafe fn ptr_into_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self {
875 let s = CStr::from_ptr(ptr as *mut c_char);
876 let s = s.to_str().unwrap().to_string();
877 free(ptr);
878 s
879 }
880 unsafe fn ptr_as_alpm_list_item(_handle: &'a Alpm, ptr: *mut c_void) -> Self::Borrow {
881 let s = CStr::from_ptr(ptr as *mut c_char);
882 s.to_str().unwrap()
883 }
884}
885
886#[cfg(test)]
887mod tests {
888 use super::*;
889 use crate::SigLevel;
890
891 #[test]
892 fn test_depends_list_debug() {
893 let handle = Alpm::new("/", "tests/db").unwrap();
894 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
895 let pkg = db.pkg("linux").unwrap();
896
897 println!("{:#?}", db.pkgs());
898 println!("{:#?}", pkg.depends());
899 }
900
901 #[test]
902 fn test_depends_list_free() {
903 let handle = Alpm::new("/", "tests/db").unwrap();
904 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
905 let pkg = db.pkg("linux").unwrap();
906 let depends = pkg.depends();
907 assert_eq!(depends.first().unwrap().to_string(), "coreutils");
908 }
909
910 #[test]
911 fn test_is_empty() {
912 let handle = Alpm::new("/", "tests/db").unwrap();
913 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
914 let pkg = db.pkg("linux").unwrap();
915 let depends = pkg.depends();
916 assert!(!depends.is_empty());
917
918 let pkg = db.pkg("tzdata").unwrap();
919 let depends = pkg.depends();
920 assert!(depends.is_empty());
921 }
922
923 #[test]
924 fn test_string_list_free() {
925 let handle = Alpm::new("/", "tests/db").unwrap();
926 handle.register_syncdb("community", SigLevel::NONE).unwrap();
927 handle.register_syncdb("extra", SigLevel::NONE).unwrap();
928 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
929 let pkg = db.pkg("linux").unwrap();
930 let required_by = pkg.required_by();
931 assert_eq!("acpi_call", required_by.first().unwrap());
932 }
933
934 #[test]
935 fn test_str_list_free() {
936 let handle = Alpm::new("/", "tests/db").unwrap();
937 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
938 let pkg = db.pkg("pacman").unwrap();
939 let groups = pkg.groups();
940 assert_eq!("base", groups.first().unwrap());
941 }
942
943 #[test]
944 fn test_push() {
945 let handle = Alpm::new("/", "tests/db").unwrap();
946 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
947 let pkg = db.pkg("pacman").unwrap();
948
949 let mut list = AlpmListMut::new(&handle);
950 list.push(pkg);
951 assert_eq!(list.first().unwrap().name(), "pacman");
952
953 let mut list = AlpmListMut::new(&handle);
954 list.push(Depend::new("a"));
955 list.push(Depend::new("b"));
956 list.push(Depend::new("c"));
957
958 let mut list = AlpmListMut::new(&handle);
959 list.push("a".to_string());
960 list.push("b".to_string());
961 list.push("c".to_string());
962
963 let mut list = AlpmListMut::new(&handle);
964 list.push("a".to_string());
965 list.push_str("b");
966 list.push_str("c");
967 }
968
969 #[test]
970 fn test_retain() {
971 let handle = Alpm::new("/", "tests/db").unwrap();
972 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
973 let mut pkgs = db.pkgs().to_list_mut();
974 pkgs.retain(|p| p.name().starts_with('a'));
975
976 assert!(!pkgs.is_empty());
977 pkgs.iter().for_each(|p| assert!(p.name().starts_with('a')));
978 }
979
980 #[test]
981 fn test_into_raw_alpm_list() {
982 let handle = Alpm::new("/", "tests/db").unwrap();
983 let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
984 let pkg = db.pkg("linux").unwrap();
985 assert_eq!(handle.syncdbs().to_list_mut().remove_list(0).len(), 1);
986 pkg.sync_new_version(handle.syncdbs());
987 pkg.sync_new_version(&handle.syncdbs().to_list_mut().remove_list(0));
988 pkg.sync_new_version(vec![db].into_iter());
989 pkg.sync_new_version(vec![db].iter());
990 }
991
992 #[test]
993 fn test_into_raw_alpm_list2() {
994 let mut handle = Alpm::new("/", "tests/db").unwrap();
995
996 let list = vec![Depend::new("foo")];
997 handle.set_assume_installed(list.iter()).unwrap();
998 }
999}