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_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}
17pub trait AlpmListItem<T> {
20 fn new(data_ptr: *mut c_void) -> Self;
21 fn to_ptr(&self) -> *mut c_void;
22}
23
24pub 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 }
114}
115pub 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}