#
alpm/
list_mut.rs

    1use alpm_sys::*;
    2
    3use crate::{
    4    AlpmList, Backup, Conflict, Db, DbMut, Dep, DepMissing, Depend, DependMissing, FileConflict,
    5    IntoAlpmListItem, Iter, LoadedPackage, OwnedConflict, OwnedFileConflict, Package, Pkg, free,
    6};
    7
    8use std::ffi::c_void;
    9use std::fmt;
    10use std::fmt::Debug;
    11use std::iter::FromIterator;
    12use std::marker::PhantomData;
    13use std::mem::ManuallyDrop;
    14use std::ptr;
    15
    16unsafe extern "C" {
    17    unsafe fn calloc(n: usize, s: usize) -> *mut c_void;
    18    unsafe fn memcpy(dst: *mut c_void, src: *const c_void, n: usize);
    19}
    20
    21fn alloc_str(s: &str) -> *mut c_void {
    22    let buf = unsafe { calloc(s.len() + 1, 1) };
    23    unsafe {
    24        memcpy(buf, s.as_ptr() as _, s.len());
    25    }
    26    buf as _
    27}
    28
    29#[doc(hidden)]
    30pub unsafe trait BorrowAlpmListItem<'a> {
    31    type Borrow: IntoAlpmListItem;
    32}
    33
    34#[doc(hidden)]
    35pub unsafe trait IntoAlpmListPtr: Sized {
    36    type Output: IntoAlpmListItem;
    37    fn into_ptr(self) -> *mut c_void {
    38        ManuallyDrop::new(self).as_ptr()
    39    }
    40    fn as_ptr(&self) -> *mut c_void;
    41}
    42
    43pub struct AlpmListMut<T: IntoAlpmListItem> {
    44    _marker: PhantomData<T>,
    45    list: *mut alpm_list_t,
    46}
    47
    48unsafe impl<T: IntoAlpmListItem + Send> Send for AlpmListMut<T> {}
    49unsafe impl<T: IntoAlpmListItem + Sync> Sync for AlpmListMut<T> {}
    50
    51impl<'a, T: IntoAlpmListItem + BorrowAlpmListItem<'a>> fmt::Debug for AlpmListMut<T>
    52where
    53    T::Borrow: Debug,
    54{
    55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    56        fmt::Debug::fmt(&self.list(), f)
    57    }
    58}
    59
    60pub struct IntoIter<T: IntoAlpmListItem> {
    61    list: *mut alpm_list_t,
    62    start: *mut alpm_list_t,
    63    _marker: PhantomData<T>,
    64}
    65
    66unsafe impl<T: IntoAlpmListItem + Send> Send for IntoIter<T> {}
    67unsafe impl<T: IntoAlpmListItem + Sync> Sync for IntoIter<T> {}
    68
    69impl<'a, T: IntoAlpmListItem + BorrowAlpmListItem<'a>> Debug for IntoIter<T>
    70where
    71    T::Borrow: Debug,
    72{
    73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    74        unsafe {
    75            f.debug_struct("Iter")
    76                .field("list", &AlpmList::<T::Borrow>::from_ptr(self.list))
    77                .finish()
    78        }
    79    }
    80}
    81
    82impl<T: IntoAlpmListItem> Drop for AlpmListMut<T> {
    83    fn drop(&mut self) {
    84        let mut list = self.list;
    85        let start = self.list;
    86
    87        while !list.is_null() {
    88            unsafe { T::drop_item((*list).data) };
    89            list = unsafe { (*list).next };
    90        }
    91
    92        unsafe { alpm_list_free(start) }
    93    }
    94}
    95
    96impl<T: IntoAlpmListItem> IntoIterator for AlpmListMut<T> {
    97    type IntoIter = IntoIter<T>;
    98    type Item = T;
    99
    100    fn into_iter(self) -> Self::IntoIter {
    101        let list = ManuallyDrop::new(self);
    102        IntoIter {
    103            list: list.list,
    104            start: list.list,
    105            _marker: PhantomData,
    106        }
    107    }
    108}
    109
    110impl<'a, T: IntoAlpmListItem> IntoIterator for &'a AlpmListMut<T>
    111where
    112    T: BorrowAlpmListItem<'a>,
    113{
    114    type IntoIter = Iter<'a, T::Borrow>;
    115    type Item = T::Borrow;
    116
    117    fn into_iter(self) -> Self::IntoIter {
    118        self.list().into_iter()
    119    }
    120}
    121
    122impl<T: IntoAlpmListPtr> FromIterator<T> for AlpmListMut<T::Output> {
    123    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
    124        let mut list = AlpmListMut::new();
    125        list.extend(iter);
    126        list
    127    }
    128}
    129
    130impl<T: IntoAlpmListPtr> Extend<T> for AlpmListMut<T::Output> {
    131    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
    132        for item in iter {
    133            self.push(item);
    134        }
    135    }
    136}
    137
    138impl<'a, T: IntoAlpmListItem + BorrowAlpmListItem<'a>> AlpmListMut<T> {
    139    pub fn list(&self) -> AlpmList<T::Borrow> {
    140        unsafe { AlpmList::from_ptr(self.list) }
    141    }
    142}
    143
    144impl<T: IntoAlpmListItem> Default for AlpmListMut<T> {
    145    fn default() -> Self {
    146        Self::new()
    147    }
    148}
    149
    150impl<T: IntoAlpmListItem> AlpmListMut<T> {
    151    pub(crate) unsafe fn from_ptr(list: *mut alpm_list_t) -> AlpmListMut<T> {
    152        AlpmListMut {
    153            list,
    154            _marker: PhantomData,
    155        }
    156    }
    157
    158    pub fn new() -> AlpmListMut<T> {
    159        AlpmListMut {
    160            list: ptr::null_mut(),
    161            _marker: PhantomData,
    162        }
    163    }
    164
    165    pub fn len(&self) -> usize {
    166        unsafe { alpm_list_count(self.list) }
    167    }
    168
    169    pub fn retain<F>(&mut self, mut f: F)
    170    where
    171        F: FnMut(&T) -> bool,
    172    {
    173        let mut curr = self.list;
    174
    175        while !curr.is_null() {
    176            let item = unsafe { ManuallyDrop::new(T::into_list_item((*curr).data)) };
    177            let next = unsafe { (*curr).next };
    178            if !f(&item) {
    179                ManuallyDrop::into_inner(item);
    180                unsafe { self.list = alpm_list_remove_item(self.list, curr) };
    181                unsafe { free(curr as _) };
    182            }
    183            curr = next;
    184        }
    185    }
    186
    187    pub fn remove(&mut self, n: usize) -> Option<T> {
    188        if n >= self.len() {
    189            return None;
    190        }
    191
    192        let item = unsafe { alpm_list_nth(self.list, n) };
    193        unsafe { self.list = alpm_list_remove_item(self.list, item) };
    194        let ret = unsafe { Some(T::into_list_item((*item).data)) };
    195        unsafe { free(item as _) };
    196        ret
    197    }
    198
    199    pub fn pop(&mut self) -> Option<T> {
    200        if self.list.is_null() {
    201            return None;
    202        }
    203
    204        let last = unsafe { (*self.list).prev };
    205        unsafe { self.list = alpm_list_remove_item(self.list, last) };
    206        let ret = unsafe { Some(T::into_list_item((*last).data)) };
    207        unsafe { free(last as _) };
    208        ret
    209    }
    210}
    211
    212impl<T: IntoAlpmListItem> AlpmListMut<T> {
    213    pub fn push<U: IntoAlpmListPtr<Output = T>>(&mut self, t: U) {
    214        unsafe { self.list = alpm_list_add(self.list, U::into_ptr(t)) }
    215    }
    216}
    217
    218impl AlpmListMut<String> {
    219    pub fn push_str(&mut self, s: &str) {
    220        let s = alloc_str(s);
    221        unsafe { self.list = alpm_list_add(self.list, s as *mut c_void) };
    222    }
    223}
    224
    225// cant deref so manual impl
    226impl<T: IntoAlpmListItem> AlpmListMut<T> {
    227    pub fn is_empty(&self) -> bool {
    228        self.list.is_null()
    229    }
    230}
    231
    232impl<'a, T: IntoAlpmListItem + BorrowAlpmListItem<'a>> AlpmListMut<T> {
    233    pub fn first(&self) -> Option<T::Borrow> {
    234        self.list().first()
    235    }
    236
    237    pub fn last(&self) -> Option<T::Borrow> {
    238        self.list().last()
    239    }
    240
    241    pub fn iter(&self) -> Iter<T::Borrow> {
    242        unsafe { AlpmList::from_ptr(self.list).into_iter() }
    243    }
    244}
    245
    246impl<T: IntoAlpmListItem> Drop for IntoIter<T> {
    247    fn drop(&mut self) {
    248        let mut list = self.list;
    249
    250        while !list.is_null() {
    251            unsafe { T::drop_item((*list).data) };
    252            list = unsafe { (*list).next };
    253        }
    254
    255        unsafe { alpm_list_free(self.start) }
    256    }
    257}
    258
    259impl<T: IntoAlpmListItem> IntoIter<T> {
    260    fn next_data(&mut self) -> Option<*mut c_void> {
    261        if self.list.is_null() {
    262            None
    263        } else {
    264            let data = unsafe { (*(self.list)).data };
    265            self.list = unsafe { alpm_list_next(self.list) };
    266
    267            Some(data)
    268        }
    269    }
    270}
    271
    272impl<T: IntoAlpmListItem> Iterator for IntoIter<T> {
    273    type Item = T;
    274
    275    fn next(&mut self) -> Option<Self::Item> {
    276        unsafe { self.next_data().map(|i| T::into_list_item(i)) }
    277    }
    278
    279    fn size_hint(&self) -> (usize, Option<usize>) {
    280        let size = unsafe { alpm_list_count(self.list) };
    281        (size, Some(size))
    282    }
    283}
    284
    285// ptr impl
    286
    287unsafe impl<'a, T: IntoAlpmListPtr> IntoAlpmListPtr for &&'a T
    288where
    289    &'a T::Output: BorrowAlpmListItem<'a>,
    290{
    291    type Output = <&'a T::Output as BorrowAlpmListItem<'a>>::Borrow;
    292    fn as_ptr(&self) -> *mut c_void {
    293        T::as_ptr(*self)
    294    }
    295}
    296
    297unsafe impl IntoAlpmListPtr for Depend {
    298    type Output = Self;
    299    fn as_ptr(&self) -> *mut c_void {
    300        Dep::as_ptr(self) as _
    301    }
    302}
    303
    304unsafe impl IntoAlpmListPtr for &Dep {
    305    type Output = Self;
    306    fn as_ptr(&self) -> *mut c_void {
    307        Dep::as_ptr(self) as _
    308    }
    309}
    310
    311unsafe impl IntoAlpmListPtr for &Pkg {
    312    type Output = Self;
    313    fn as_ptr(&self) -> *mut c_void {
    314        Pkg::as_ptr(self) as _
    315    }
    316}
    317
    318unsafe impl IntoAlpmListPtr for &Package {
    319    type Output = Self;
    320    fn as_ptr(&self) -> *mut c_void {
    321        Pkg::as_ptr(self) as _
    322    }
    323}
    324
    325unsafe impl IntoAlpmListPtr for LoadedPackage<'_> {
    326    type Output = Self;
    327    fn as_ptr(&self) -> *mut c_void {
    328        Pkg::as_ptr(self) as _
    329    }
    330}
    331
    332unsafe impl IntoAlpmListPtr for &Db {
    333    type Output = Self;
    334    fn as_ptr(&self) -> *mut c_void {
    335        Db::as_ptr(self) as _
    336    }
    337}
    338
    339unsafe impl IntoAlpmListPtr for DbMut<'_> {
    340    type Output = Self;
    341    fn as_ptr(&self) -> *mut c_void {
    342        Db::as_ptr(self) as _
    343    }
    344}
    345
    346unsafe impl IntoAlpmListPtr for DependMissing {
    347    type Output = Self;
    348    fn as_ptr(&self) -> *mut c_void {
    349        DepMissing::as_ptr(self) as _
    350    }
    351}
    352
    353unsafe impl IntoAlpmListPtr for &DepMissing {
    354    type Output = Self;
    355    fn as_ptr(&self) -> *mut c_void {
    356        DepMissing::as_ptr(self) as _
    357    }
    358}
    359
    360unsafe impl IntoAlpmListPtr for &Conflict {
    361    type Output = Self;
    362    fn as_ptr(&self) -> *mut c_void {
    363        Conflict::as_ptr(self) as _
    364    }
    365}
    366
    367unsafe impl IntoAlpmListPtr for OwnedConflict {
    368    type Output = Self;
    369    fn as_ptr(&self) -> *mut c_void {
    370        Conflict::as_ptr(self) as _
    371    }
    372}
    373
    374unsafe impl IntoAlpmListPtr for &FileConflict {
    375    type Output = Self;
    376    fn as_ptr(&self) -> *mut c_void {
    377        FileConflict::as_ptr(self) as _
    378    }
    379}
    380
    381unsafe impl IntoAlpmListPtr for OwnedFileConflict {
    382    type Output = Self;
    383    fn as_ptr(&self) -> *mut c_void {
    384        FileConflict::as_ptr(self) as _
    385    }
    386}
    387
    388unsafe impl IntoAlpmListPtr for &Backup {
    389    type Output = Self;
    390    fn as_ptr(&self) -> *mut c_void {
    391        Backup::as_ptr(self) as _
    392    }
    393}
    394
    395unsafe impl IntoAlpmListPtr for String {
    396    type Output = Self;
    397    fn as_ptr(&self) -> *mut c_void {
    398        alloc_str(self)
    399    }
    400    fn into_ptr(self) -> *mut c_void {
    401        alloc_str(&self)
    402    }
    403}
    404
    405unsafe impl IntoAlpmListPtr for &String {
    406    type Output = String;
    407    fn as_ptr(&self) -> *mut c_void {
    408        alloc_str(self)
    409    }
    410    fn into_ptr(self) -> *mut c_void {
    411        alloc_str(&self)
    412    }
    413}
    414
    415unsafe impl IntoAlpmListPtr for &str {
    416    type Output = String;
    417    fn as_ptr(&self) -> *mut c_void {
    418        alloc_str(&self)
    419    }
    420    fn into_ptr(self) -> *mut c_void {
    421        alloc_str(&self)
    422    }
    423}
    424
    425// ptr impl on &T because String is special
    426
    427unsafe impl IntoAlpmListPtr for &&str {
    428    type Output = String;
    429    fn as_ptr(&self) -> *mut c_void {
    430        alloc_str(self)
    431    }
    432    fn into_ptr(self) -> *mut c_void {
    433        alloc_str(&self)
    434    }
    435}
    436
    437unsafe impl<'a> IntoAlpmListPtr for &'a Depend {
    438    type Output = &'a Dep;
    439    fn as_ptr(&self) -> *mut c_void {
    440        Dep::as_ptr(self) as _
    441    }
    442}
    443
    444unsafe impl<'a> IntoAlpmListPtr for &&'a Dep {
    445    type Output = &'a Dep;
    446    fn as_ptr(&self) -> *mut c_void {
    447        Dep::as_ptr(self) as _
    448    }
    449}
    450
    451unsafe impl<'a> IntoAlpmListPtr for &&'a Package {
    452    type Output = &'a Pkg;
    453    fn as_ptr(&self) -> *mut c_void {
    454        Pkg::as_ptr(self) as _
    455    }
    456}
    457
    458unsafe impl<'a> IntoAlpmListPtr for &&'a Pkg {
    459    type Output = &'a Pkg;
    460    fn as_ptr(&self) -> *mut c_void {
    461        Pkg::as_ptr(self) as _
    462    }
    463}
    464
    465unsafe impl<'a> IntoAlpmListPtr for &LoadedPackage<'a> {
    466    type Output = &'a Pkg;
    467    fn as_ptr(&self) -> *mut c_void {
    468        Pkg::as_ptr(self) as _
    469    }
    470}
    471
    472unsafe impl<'a> IntoAlpmListPtr for &&'a Db {
    473    type Output = &'a Db;
    474    fn as_ptr(&self) -> *mut c_void {
    475        Db::as_ptr(self) as _
    476    }
    477}
    478
    479unsafe impl<'a> IntoAlpmListPtr for &DbMut<'a> {
    480    type Output = DbMut<'a>;
    481    fn as_ptr(&self) -> *mut c_void {
    482        Db::as_ptr(self) as _
    483    }
    484}
    485
    486unsafe impl<'a> IntoAlpmListPtr for &'a DependMissing {
    487    type Output = &'a DepMissing;
    488    fn as_ptr(&self) -> *mut c_void {
    489        DepMissing::as_ptr(self) as _
    490    }
    491}
    492
    493unsafe impl<'a> IntoAlpmListPtr for &&'a DepMissing {
    494    type Output = &'a DepMissing;
    495    fn as_ptr(&self) -> *mut c_void {
    496        DepMissing::as_ptr(self) as _
    497    }
    498}
    499
    500unsafe impl<'a> IntoAlpmListPtr for &&'a Conflict {
    501    type Output = &'a Conflict;
    502    fn as_ptr(&self) -> *mut c_void {
    503        Conflict::as_ptr(self) as _
    504    }
    505}
    506
    507unsafe impl<'a> IntoAlpmListPtr for &'a OwnedConflict {
    508    type Output = &'a Conflict;
    509    fn as_ptr(&self) -> *mut c_void {
    510        Conflict::as_ptr(self) as _
    511    }
    512}
    513
    514unsafe impl<'a> IntoAlpmListPtr for &&'a FileConflict {
    515    type Output = &'a FileConflict;
    516    fn as_ptr(&self) -> *mut c_void {
    517        FileConflict::as_ptr(self) as _
    518    }
    519}
    520
    521unsafe impl<'a> IntoAlpmListPtr for &'a OwnedFileConflict {
    522    type Output = &'a FileConflict;
    523    fn as_ptr(&self) -> *mut c_void {
    524        FileConflict::as_ptr(self) as _
    525    }
    526}
    527
    528unsafe impl<'a> IntoAlpmListPtr for &&'a Backup {
    529    type Output = &'a Backup;
    530    fn as_ptr(&self) -> *mut c_void {
    531        Backup::as_ptr(self) as _
    532    }
    533}
    534
    535// borrow impl
    536
    537unsafe impl<'a, T: BorrowAlpmListItem<'a>> BorrowAlpmListItem<'a> for &T {
    538    type Borrow = T::Borrow;
    539}
    540
    541unsafe impl<'a> BorrowAlpmListItem<'a> for Depend {
    542    type Borrow = &'a Dep;
    543}
    544
    545unsafe impl<'a> BorrowAlpmListItem<'a> for DbMut<'a> {
    546    type Borrow = DbMut<'a>;
    547}
    548
    549unsafe impl<'a> BorrowAlpmListItem<'a> for &Db {
    550    type Borrow = &'a Db;
    551}
    552
    553unsafe impl<'a> BorrowAlpmListItem<'a> for &Dep {
    554    type Borrow = &'a Dep;
    555}
    556
    557unsafe impl<'a> BorrowAlpmListItem<'a> for &Pkg {
    558    type Borrow = &'a Pkg;
    559}
    560
    561unsafe impl<'a> BorrowAlpmListItem<'a> for &Package {
    562    type Borrow = &'a Pkg;
    563}
    564
    565unsafe impl<'a> BorrowAlpmListItem<'a> for LoadedPackage<'a> {
    566    type Borrow = &'a Pkg;
    567}
    568
    569unsafe impl<'a> BorrowAlpmListItem<'a> for DependMissing {
    570    type Borrow = &'a DepMissing;
    571}
    572
    573unsafe impl<'a> BorrowAlpmListItem<'a> for &DepMissing {
    574    type Borrow = &'a DepMissing;
    575}
    576
    577unsafe impl<'a> BorrowAlpmListItem<'a> for &Conflict {
    578    type Borrow = &'a Conflict;
    579}
    580
    581unsafe impl<'a> BorrowAlpmListItem<'a> for OwnedConflict {
    582    type Borrow = &'a Conflict;
    583}
    584
    585unsafe impl<'a> BorrowAlpmListItem<'a> for &FileConflict {
    586    type Borrow = &'a FileConflict;
    587}
    588
    589unsafe impl<'a> BorrowAlpmListItem<'a> for OwnedFileConflict {
    590    type Borrow = &'a FileConflict;
    591}
    592
    593unsafe impl<'a> BorrowAlpmListItem<'a> for &Backup {
    594    type Borrow = &'a Backup;
    595}
    596
    597unsafe impl<'a> BorrowAlpmListItem<'a> for String {
    598    type Borrow = &'a str;
    599}
    600
    601unsafe impl<'a> BorrowAlpmListItem<'a> for &str {
    602    type Borrow = &'a str;
    603}
    604
    605#[cfg(test)]
    606mod tests {
    607    use super::*;
    608    use crate::{Alpm, SigLevel};
    609
    610    #[test]
    611    fn test_depends_list_free() {
    612        let mut list = AlpmListMut::new();
    613        list.push(Depend::new("aaaa"));
    614        list.push(Depend::new("aaaa"));
    615        list.push(Depend::new("aaaa"));
    616        list.push(Depend::new("aaaa"));
    617    }
    618
    619    #[test]
    620    fn test_depends_list_free_iter() {
    621        let mut list = AlpmListMut::new();
    622        list.push(Depend::new("aaaa"));
    623        list.push(Depend::new("aaaa"));
    624        list.push(Depend::new("aaaa"));
    625        list.push(Depend::new("aaaa"));
    626        let mut iter = list.into_iter();
    627        iter.next().unwrap();
    628    }
    629
    630    #[test]
    631    fn test_depends_list_pop() {
    632        let mut list = AlpmListMut::new();
    633        list.push(Depend::new("aaaa"));
    634        list.push(Depend::new("bbbb"));
    635        list.push(Depend::new("cccc"));
    636        list.push(Depend::new("dddd"));
    637        assert_eq!(list.pop().unwrap().name(), "dddd");
    638        assert_eq!(list.pop().unwrap().name(), "cccc");
    639        assert_eq!(list.pop().unwrap().name(), "bbbb");
    640        assert_eq!(list.pop().unwrap().name(), "aaaa");
    641        assert_eq!(list.pop(), None);
    642    }
    643
    644    #[test]
    645    fn test_depends_list_remove() {
    646        let mut list = AlpmListMut::new();
    647        list.push(Depend::new("aaaa"));
    648        list.push(Depend::new("bbbb"));
    649        list.push(Depend::new("cccc"));
    650        list.push(Depend::new("dddd"));
    651        assert_eq!(list.remove(0).unwrap().name(), "aaaa");
    652        assert_eq!(list.remove(2).unwrap().name(), "dddd");
    653        assert_eq!(list.remove(3), None);
    654    }
    655
    656    #[test]
    657    fn test_depends_list_from_iter() {
    658        let vec = vec![
    659            Depend::new("aaaa"),
    660            Depend::new("bbbb"),
    661            Depend::new("cccc"),
    662            Depend::new("dddd"),
    663        ];
    664
    665        let list = vec.clone().into_iter().collect::<AlpmListMut<_>>();
    666        let mut iter = list.iter();
    667
    668        assert_eq!(iter.next().unwrap().name(), "aaaa");
    669        assert_eq!(iter.next().unwrap().name(), "bbbb");
    670        assert_eq!(iter.next().unwrap().name(), "cccc");
    671        assert_eq!(iter.next().unwrap().name(), "dddd");
    672        assert_eq!(iter.next(), None);
    673    }
    674
    675    #[test]
    676    fn test_depends_list_debug() {
    677        let handle = Alpm::new("/", "tests/db").unwrap();
    678        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    679        let pkg = db.pkg("linux").unwrap();
    680
    681        println!("{:#?}", db.pkgs());
    682        println!("{:#?}", pkg.depends());
    683    }
    684
    685    #[test]
    686    fn test_depends_list_free2() {
    687        let handle = Alpm::new("/", "tests/db").unwrap();
    688        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    689        let pkg = db.pkg("linux").unwrap();
    690        let depends = pkg.depends();
    691        assert_eq!(depends.first().unwrap().to_string(), "coreutils");
    692    }
    693
    694    #[test]
    695    fn test_is_empty() {
    696        let handle = Alpm::new("/", "tests/db").unwrap();
    697        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    698        let pkg = db.pkg("linux").unwrap();
    699        let depends = pkg.depends();
    700        assert!(!depends.is_empty());
    701
    702        let pkg = db.pkg("tzdata").unwrap();
    703        let depends = pkg.depends();
    704        assert!(depends.is_empty());
    705    }
    706
    707    #[test]
    708    fn test_string_list_free() {
    709        let handle = Alpm::new("/", "tests/db").unwrap();
    710        handle.register_syncdb("community", SigLevel::NONE).unwrap();
    711        handle.register_syncdb("extra", SigLevel::NONE).unwrap();
    712        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    713        let pkg = db.pkg("linux").unwrap();
    714        let required_by = pkg.required_by();
    715        assert_eq!("acpi_call", required_by.first().unwrap());
    716    }
    717
    718    #[test]
    719    fn test_str_list_free() {
    720        let handle = Alpm::new("/", "tests/db").unwrap();
    721        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    722        let pkg = db.pkg("pacman").unwrap();
    723        let groups = pkg.groups();
    724        assert_eq!("base", groups.first().unwrap());
    725    }
    726
    727    #[test]
    728    fn test_push() {
    729        let handle = Alpm::new("/", "tests/db").unwrap();
    730        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    731        let pkg = db.pkg("pacman").unwrap();
    732
    733        let mut list = AlpmListMut::new();
    734        list.push(pkg);
    735        assert_eq!(list.first().unwrap().name(), "pacman");
    736
    737        let mut list = AlpmListMut::new();
    738        list.push(Depend::new("a"));
    739        list.push(Depend::new("b"));
    740        list.push(Depend::new("c"));
    741
    742        let mut list = AlpmListMut::new();
    743        list.push("a".to_string());
    744        list.push("b".to_string());
    745        list.push("c".to_string());
    746
    747        let mut list = AlpmListMut::new();
    748        list.push("a".to_string());
    749        list.push_str("b");
    750        list.push_str("c");
    751    }
    752
    753    #[test]
    754    fn test_retain() {
    755        let handle = Alpm::new("/", "tests/db").unwrap();
    756        let db = handle.register_syncdb("core", SigLevel::NONE).unwrap();
    757        let mut pkgs = db.pkgs().to_list_mut();
    758        pkgs.retain(|p| p.name().starts_with('a'));
    759
    760        assert!(!pkgs.is_empty());
    761        pkgs.iter().for_each(|p| assert!(p.name().starts_with('a')));
    762    }
    763}