aorist_extendr_api/wrapper/list.rs
1use super::*;
2
3#[derive(Debug, PartialEq, Clone)]
4pub struct List {
5 pub(crate) robj: Robj,
6}
7
8impl Default for List {
9 fn default() -> Self {
10 List::new()
11 }
12}
13
14impl List {
15 /// Create a new, empty list.
16 /// ```
17 /// use extendr_api::prelude::*;
18 /// test! {
19 /// let list = List::new();
20 /// assert_eq!(list.is_list(), true);
21 /// assert_eq!(list.len(), 0);
22 /// }
23 /// ```
24 pub fn new() -> List {
25 let values: &[Robj] = &[];
26 List::from_values(values)
27 }
28
29 /// Wrapper for creating list (VECSXP) objects.
30 /// ```
31 /// use extendr_api::prelude::*;
32 /// test! {
33 /// let list = r!(List::from_values(&[r!(0), r!(1), r!(2)]));
34 /// assert_eq!(list.is_list(), true);
35 /// assert_eq!(list.len(), 3);
36 /// }
37 /// ```
38 pub fn from_values<V>(values: V) -> Self
39 where
40 V: IntoIterator,
41 V::IntoIter: ExactSizeIterator,
42 V::Item: Into<Robj>,
43 {
44 Self {
45 robj: make_vector(VECSXP, values),
46 }
47 }
48
49 pub fn from_pairs<V>(pairs: V) -> Self
50 where
51 V: IntoIterator,
52 V::IntoIter: ExactSizeIterator + Clone,
53 V::Item: Into<(&'static str, Robj)>,
54 {
55 let iter = pairs.into_iter();
56 let res = List::from_values(iter.clone().map(|kv| {
57 let (_, v) = kv.into();
58 v
59 }));
60 res.set_names(iter.map(|kv| {
61 let (k, _) = kv.into();
62 k
63 }))
64 .unwrap()
65 .as_list()
66 .unwrap()
67 }
68
69 /// Return an iterator over the values of this list.
70 /// ```
71 /// use extendr_api::prelude::*;
72 /// test! {
73 /// let mut robj = list!(1, 2, 3);
74 /// let objects : Vec<_> = robj.as_list().unwrap().values().collect();
75 /// assert_eq!(objects, vec![r!(1), r!(2), r!(3)]);
76 /// }
77 /// ```
78 pub fn values(&self) -> ListIter {
79 ListIter::from_parts(self.robj.clone(), 0, self.robj.len())
80 }
81
82 /// Return an iterator over the names and values of this list.
83 /// ```
84 /// use extendr_api::prelude::*;
85 /// test! {
86 /// let mut robj = list!(a=1, 2);
87 /// let names_and_values : Vec<_> = robj.as_list().unwrap().iter().collect();
88 /// assert_eq!(names_and_values, vec![("a", r!(1)), ("", r!(2))]);
89 /// }
90 /// ```
91 pub fn iter(&self) -> NamedListIter {
92 self.names()
93 .map(|n| n.zip(self.values()))
94 .unwrap_or_else(|| StrIter::new().zip(ListIter::new()))
95 }
96}
97
98impl IntoIterator for List {
99 type IntoIter = NamedListIter;
100 type Item = (&'static str, Robj);
101
102 /// Convert a List into an interator, consuming the list.
103 /// ```
104 /// use extendr_api::prelude::*;
105 /// test! {
106 /// let list = list!(a=1, 2).as_list().unwrap();
107 /// let vec : Vec<_> = list.into_iter().collect();
108 /// assert_eq!(vec, vec![("a", r!(1)), ("", r!(2))]);
109 /// }
110 /// ```
111 fn into_iter(self) -> Self::IntoIter {
112 self.iter()
113 }
114}
115
116/// Iterator over the objects in a VECSXP, EXPRSXP or WEAKREFSXP.
117///
118/// ```
119/// use extendr_api::prelude::*;
120/// test! {
121/// let my_list = list!(a = 1, b = 2);
122/// let mut total = 0;
123/// for robj in my_list.as_list().unwrap().values() {
124/// if let Some(val) = robj.as_integer() {
125/// total += val;
126/// }
127/// }
128/// assert_eq!(total, 3);
129///
130/// for name in my_list.names().unwrap() {
131/// assert!(name == "a" || name == "b")
132/// }
133/// }
134/// ```
135#[derive(Clone)]
136pub struct ListIter {
137 robj: Robj,
138 i: usize,
139 len: usize,
140}
141
142impl Default for ListIter {
143 fn default() -> Self {
144 ListIter::new()
145 }
146}
147
148impl ListIter {
149 // A new, empty list iterator.
150 pub fn new() -> Self {
151 ListIter::from_parts(().into(), 0, 0)
152 }
153
154 pub(crate) fn from_parts(robj: Robj, i: usize, len: usize) -> Self {
155 Self { robj, i, len }
156 }
157}
158
159impl Iterator for ListIter {
160 type Item = Robj;
161
162 fn size_hint(&self) -> (usize, Option<usize>) {
163 (self.len, Some(self.len))
164 }
165
166 fn next(&mut self) -> Option<Self::Item> {
167 let i = self.i;
168 self.i += 1;
169 if i >= self.len {
170 None
171 } else {
172 Some(unsafe { new_owned(VECTOR_ELT(self.robj.get(), i as isize)) })
173 }
174 }
175
176 fn nth(&mut self, n: usize) -> Option<Self::Item> {
177 self.i += n;
178 self.next()
179 }
180}
181
182impl ExactSizeIterator for ListIter {
183 /// Length of a list iterator.
184 fn len(&self) -> usize {
185 self.len - self.i
186 }
187}
188
189/// You can use the FromList wrapper to coerce a Robj into a list.
190/// ```
191/// use extendr_api::prelude::*;
192/// test! {
193/// let list = list!(1, 2);
194/// let vec : FromList<Vec<i32>> = list.try_into()?;
195/// assert_eq!(vec.0, vec![1, 2]);
196/// }
197/// ```
198pub struct FromList<T>(pub T);
199
200impl<T> TryFrom<Robj> for FromList<Vec<T>>
201where
202 T: TryFrom<Robj>,
203 <T as TryFrom<Robj>>::Error: Into<Error>,
204{
205 type Error = Error;
206
207 /// You can use the FromList wrapper to coerce a Robj into a list.
208 /// ```
209 /// use extendr_api::prelude::*;
210 /// test! {
211 /// let list = list!(1, 2);
212 /// let vec : FromList<Vec<i32>> = list.try_into()?;
213 /// assert_eq!(vec.0, vec![1, 2]);
214 /// }
215 /// ```
216 fn try_from(robj: Robj) -> Result<Self> {
217 let listiter: ListIter = robj.try_into()?;
218 let res: Result<Vec<_>> = listiter
219 .map(|robj| T::try_from(robj).map_err(|e| e.into()))
220 .collect();
221 res.map(FromList)
222 }
223}
224
225impl TryFrom<Robj> for ListIter {
226 type Error = Error;
227
228 /// You can pass a ListIter to a function.
229 /// ```
230 /// use extendr_api::prelude::*;
231 /// test! {
232 /// let list = list!(1, 2);
233 /// let vec : ListIter = list.try_into()?;
234 /// assert_eq!(vec.collect::<Vec<_>>(), vec![r!(1), r!(2)]);
235 /// }
236 /// ```
237 fn try_from(robj: Robj) -> Result<Self> {
238 let list: List = robj.try_into()?;
239 Ok(list.values())
240 }
241}
242
243impl From<ListIter> for Robj {
244 /// You can return a ListIter from a function.
245 /// ```
246 /// use extendr_api::prelude::*;
247 /// test! {
248 /// let listiter = list!(1, 2).as_list().unwrap().values();
249 /// assert_eq!(Robj::from(listiter), list!(1, 2));
250 /// }
251 /// ```
252 fn from(iter: ListIter) -> Self {
253 iter.robj
254 }
255}
256
257impl<'a> FromRobj<'a> for ListIter {
258 fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
259 robj.as_list().map(|l| l.values()).ok_or("Not a list.")
260 }
261}