Skip to main content

alpm_rs/
list.rs

1use std::marker::PhantomData;
2use std::os::raw::{c_char, c_void};
3use std::ptr;
4
5#[link(name = "alpm")]
6extern "C" {
7    //fn alpm_list_free(list: *mut alpm_list_t);
8    fn alpm_list_add(list: *mut alpm_list_t, data: *mut c_void) -> *mut alpm_list_t;
9}
10
11#[repr(C)]
12pub struct alpm_list_t {
13    pub(crate) data: *mut c_void,
14    pub(crate) prev: *mut alpm_list_t,
15    pub(crate) next: *mut alpm_list_t,
16}
17/// Trait to pass each item into a custom struct's constructor.
18/// Workaround to avoid copying data and loosing the alpm_list_t data pointer
19pub trait AlpmListItem<T> {
20    fn new(data_ptr: *mut c_void) -> Self;
21    fn to_ptr(&self) -> *mut c_void;
22}
23
24/// Generic almp list
25pub struct AlpmList<T> {
26    pub(crate) list: *mut alpm_list_t,
27    phantom: PhantomData<T>,
28}
29
30impl<T: AlpmListItem<T>> AlpmList<T> {
31    pub fn new(c_list: *mut alpm_list_t) -> AlpmList<T> {
32        AlpmList {
33            list: c_list,
34            phantom: PhantomData,
35        }
36    }
37
38    pub fn empty() -> AlpmList<T> {
39        AlpmList {
40            list: std::ptr::null_mut(),
41            phantom: PhantomData,
42        }
43    }
44
45    pub fn add(&mut self, item: T) {
46        unsafe {
47            self.list = alpm_list_add(self.list, item.to_ptr());
48        }
49    }
50
51    pub fn to_ptr(&self) -> *mut alpm_list_t {
52        self.list
53    }
54
55    pub fn iter(&self) -> AlpmListIterator<T> {
56        AlpmListIterator {
57            item: self.list,
58            phantom: PhantomData,
59        }
60    }
61}
62
63impl<T: AlpmListItem<T>> IntoIterator for AlpmList<T> {
64    type Item = T;
65    type IntoIter = AlpmListIterator<T>;
66    fn into_iter(self) -> Self::IntoIter {
67        self.iter()
68    }
69}
70
71impl<T: AlpmListItem<T>> IntoIterator for &AlpmList<T> {
72    type Item = T;
73    type IntoIter = AlpmListIterator<T>;
74    fn into_iter(self) -> Self::IntoIter {
75        self.iter()
76    }
77}
78
79impl<T: AlpmListItem<T>> From<*mut alpm_list_t> for AlpmList<T> {
80    fn from(c_list: *mut alpm_list_t) -> AlpmList<T> {
81        AlpmList::new(c_list)
82    }
83}
84
85pub struct AlpmListIterator<T> {
86    item: *mut alpm_list_t,
87    phantom: PhantomData<T>,
88}
89
90impl<T: AlpmListItem<T>> std::iter::Iterator for AlpmListIterator<T> {
91    type Item = T;
92
93    fn next(&mut self) -> Option<T> {
94        unsafe {
95            if self.item == ptr::null_mut() {
96                return None;
97            }
98            let data = T::new((*self.item).data);
99            self.item = (*self.item).next;
100            Some(data)
101        }
102    }
103}
104
105impl<T> Drop for AlpmList<T> {
106    fn drop(&mut self) {
107        /* unsafe{
108            if self.list != std::ptr::null_mut(){
109                causing undefined behaviours
110                alpm_list_free(self.list);
111            }
112        }*/
113    }
114}
115/*
116 impl<T: AlpmListItem<T>> std::iter::Iterator for AlpmList<T> {
117    type Item = T;
118
119    fn next(&mut self) -> Option<T> {
120        unsafe{
121            if self.current == ptr::null_mut() {
122                return None;
123            }
124
125            let data =  T::new((*self.current).data);
126            self.current = (*self.current).next;
127            Some(data)
128        }
129    }
130 }
131*/
132
133pub struct StringItem {
134    string_ptr: *const c_char,
135}
136
137impl StringItem {}
138
139impl AlpmListItem<StringItem> for StringItem {
140    fn new(data: *mut c_void) -> Self {
141        StringItem {
142            string_ptr: data as *const c_char,
143        }
144    }
145    fn to_ptr(&self) -> *mut c_void {
146        self.string_ptr as *mut c_void
147    }
148}
149
150impl<'a, T: AsRef<str> + 'a> From<T> for StringItem {
151    fn from(s: T) -> Self {
152        StringItem {
153            string_ptr: strc_noctx!(s.as_ref()),
154        }
155    }
156}
157
158pub struct StringList {
159    alpm_list: AlpmList<StringItem>,
160}
161
162impl From<&[&str]> for StringList {
163    fn from(strs: &[&str]) -> Self {
164        let mut list = StringList::empty();
165        for s in strs {
166            list.add(s.into());
167        }
168        list
169    }
170}
171
172impl From<*mut alpm_list_t> for StringList {
173    fn from(lst: *mut alpm_list_t) -> Self {
174        StringList::new(lst)
175    }
176}
177
178impl StringList {
179    pub fn empty() -> Self {
180        StringList {
181            alpm_list: AlpmList::empty(),
182        }
183    }
184
185    pub fn new(list: *mut alpm_list_t) -> Self {
186        StringList {
187            alpm_list: AlpmList::new(list),
188        }
189    }
190
191    pub fn add(&mut self, item: StringItem) {
192        self.alpm_list.add(item);
193    }
194
195    pub fn to_ptr(&self) -> *mut alpm_list_t {
196        self.alpm_list.to_ptr()
197    }
198
199    pub fn iter(&self) -> AlpmListIterator<StringItem> {
200        self.alpm_list.iter()
201    }
202}
203
204impl Drop for StringList {
205    fn drop(&mut self) {
206        unsafe {
207            for s in self.alpm_list.iter() {
208                let _ = str_fromraw!(s.string_ptr);
209            }
210        }
211    }
212}
213
214pub struct AnyListItem {
215    raw_ptr: *mut c_void,
216}
217
218impl AlpmListItem<AnyListItem> for AnyListItem {
219    fn new(ptr: *mut c_void) -> Self {
220        AnyListItem { raw_ptr: ptr }
221    }
222
223    fn to_ptr(&self) -> *mut c_void {
224        self.raw_ptr
225    }
226}
227
228pub type AnyList = AlpmList<AnyListItem>;
229
230impl AnyList {
231    pub fn into_list<T: From<*mut alpm_list_t>>(&self) -> T {
232        self.to_ptr().into()
233    }
234}