1use super::*;
2use crate::robj::Attributes;
3use extendr_ffi::{dataptr, R_xlen_t, SET_VECTOR_ELT, VECTOR_ELT};
4use std::{collections::HashMap, iter::FromIterator};
5
6#[derive(PartialEq, Clone)]
7pub struct List {
8 pub(crate) robj: Robj,
9}
10
11impl Default for List {
12 fn default() -> Self {
13 List::new(0)
14 }
15}
16
17impl List {
18 pub fn new(size: usize) -> Self {
28 let robj = Robj::alloc_vector(SEXPTYPE::VECSXP, size);
29 Self { robj }
30 }
31
32 pub fn from_values<V>(values: V) -> Self
42 where
43 V: IntoIterator,
44 V::IntoIter: ExactSizeIterator,
45 V::Item: Into<Robj>,
46 {
47 Self {
48 robj: make_vector(SEXPTYPE::VECSXP, values),
49 }
50 }
51
52 pub fn from_pairs<V>(pairs: V) -> Self
53 where
54 V: IntoIterator,
55 V::IntoIter: ExactSizeIterator + Clone,
56 V::Item: KeyValue,
57 {
58 let iter = pairs.into_iter();
59 let mut names = Vec::with_capacity(iter.len());
60 let mut values = Vec::with_capacity(iter.len());
61 for pair in iter {
62 names.push(pair.key());
63 values.push(pair.value());
64 }
65 let mut res = List::from_values(values);
66 res.as_robj_mut()
67 .set_names(names)
68 .unwrap()
69 .as_list()
70 .unwrap()
71 }
72
73 #[deprecated(
96 since = "0.8.1",
97 note = "Use `List::try_from(map)` or `map.try_into()` instead"
98 )]
99 pub fn from_hashmap<K, V>(val: HashMap<K, V>) -> Result<Self>
100 where
101 V: IntoRobj,
102 K: Into<String>,
103 {
104 val.try_into()
105 }
106
107 pub fn from_names_and_values<N, V>(names: N, values: V) -> Result<Self>
110 where
111 N: IntoIterator,
112 N::IntoIter: ExactSizeIterator,
113 N::Item: ToVectorValue + AsRef<str>,
114 V: IntoIterator,
115 V::IntoIter: ExactSizeIterator,
116 V::Item: Into<Robj>,
117 {
118 let mut list = List::from_values(values);
119 list.set_names(names)?;
120 Ok(list)
121 }
122
123 pub fn values(&self) -> ListIter {
133 ListIter::from_parts(self.robj.clone(), 0, self.robj.len())
134 }
135
136 pub fn iter(&self) -> NamedListIter {
146 self.names()
148 .map(|n| n.zip(self.values()))
149 .unwrap_or_else(|| StrIter::new(self.len()).zip(self.values()))
150 }
151
152 pub fn as_slice(&self) -> &[Robj] {
154 unsafe {
155 let data = dataptr(self.robj.get()) as *const Robj;
156 let len = self.robj.len();
157 crate::robj::vector_slice(data, len)
158 }
159 }
160
161 pub fn elt(&self, i: usize) -> Result<Robj> {
163 if i >= self.robj.len() {
164 Err(Error::OutOfRange(self.robj.clone()))
165 } else {
166 unsafe {
167 let sexp = VECTOR_ELT(self.robj.get(), i as R_xlen_t);
168 Ok(Robj::from_sexp(sexp))
169 }
170 }
171 }
172
173 pub fn set_elt(&mut self, i: usize, value: Robj) -> Result<()> {
175 single_threaded(|| unsafe {
176 if i >= self.robj.len() {
177 Err(Error::OutOfRange(self.robj.clone()))
178 } else {
179 SET_VECTOR_ELT(self.robj.get_mut(), i as R_xlen_t, value.get());
180 Ok(())
181 }
182 })
183 }
184
185 #[deprecated(
202 since = "0.8.1",
203 note = "Use `HashMap::try_from(list)` or `list.try_into()` instead"
204 )]
205 pub fn into_hashmap(self) -> HashMap<&'static str, Robj> {
206 self.try_into().unwrap()
207 }
208}
209
210impl<T> TryFrom<&List> for HashMap<&str, T>
211where
212 T: TryFrom<Robj, Error = error::Error>,
213{
214 type Error = Error;
215
216 fn try_from(value: &List) -> Result<Self> {
217 let value = value
218 .iter()
219 .map(|(name, value)| -> Result<(&str, T)> { value.try_into().map(|x| (name, x)) })
220 .collect::<Result<HashMap<_, _>>>()?;
221
222 Ok(value)
223 }
224}
225
226impl<T> TryFrom<&List> for HashMap<String, T>
227where
228 T: TryFrom<Robj, Error = error::Error>,
229{
230 type Error = Error;
231 fn try_from(value: &List) -> Result<Self> {
232 let value: HashMap<&str, _> = value.try_into()?;
233 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
234 }
235}
236
237impl TryFrom<&List> for HashMap<&str, Robj> {
241 type Error = Error;
242
243 fn try_from(value: &List) -> Result<Self> {
244 Ok(value.iter().collect())
245 }
246}
247
248impl TryFrom<&List> for HashMap<String, Robj> {
249 type Error = Error;
250 fn try_from(value: &List) -> Result<Self> {
251 let value: HashMap<&str, _> = value.try_into()?;
252 Ok(value.into_iter().map(|(k, v)| (k.to_string(), v)).collect())
253 }
254}
255
256impl<T> TryFrom<List> for HashMap<&str, T>
257where
258 T: TryFrom<Robj, Error = error::Error>,
259{
260 type Error = Error;
261
262 fn try_from(value: List) -> Result<Self> {
263 (&value).try_into()
264 }
265}
266
267impl<T> TryFrom<List> for HashMap<String, T>
268where
269 T: TryFrom<Robj, Error = error::Error>,
270{
271 type Error = Error;
272
273 fn try_from(value: List) -> Result<Self> {
274 (&value).try_into()
275 }
276}
277
278impl TryFrom<List> for HashMap<&str, Robj> {
279 type Error = Error;
280
281 fn try_from(value: List) -> Result<Self> {
282 (&value).try_into()
283 }
284}
285
286impl TryFrom<List> for HashMap<String, Robj> {
287 type Error = Error;
288
289 fn try_from(value: List) -> Result<Self> {
290 (&value).try_into()
291 }
292}
293
294impl<K, V> TryFrom<HashMap<K, V>> for List
295where
296 K: Into<String>,
297 V: IntoRobj,
298{
299 type Error = Error;
300
301 fn try_from(val: HashMap<K, V>) -> Result<Self> {
302 let (names, values): (Vec<_>, Vec<_>) = val
303 .into_iter()
304 .map(|(k, v)| (k.into(), v.into_robj()))
305 .unzip();
306 let mut res: Self = Self::from_values(values);
307 res.set_names(names)?;
308 Ok(res)
309 }
310}
311
312impl IntoIterator for List {
313 type IntoIter = NamedListIter;
314 type Item = (&'static str, Robj);
315
316 fn into_iter(self) -> Self::IntoIter {
326 self.iter()
327 }
328}
329
330#[derive(Clone)]
350pub struct ListIter {
351 robj: Robj,
352 i: usize,
353 len: usize,
354}
355
356impl Default for ListIter {
357 fn default() -> Self {
358 ListIter::new()
359 }
360}
361
362impl ListIter {
363 pub fn new() -> Self {
365 ListIter::from_parts(().into(), 0, 0)
366 }
367
368 pub(crate) fn from_parts(robj: Robj, i: usize, len: usize) -> Self {
369 Self { robj, i, len }
370 }
371}
372
373impl Iterator for ListIter {
374 type Item = Robj;
375
376 fn size_hint(&self) -> (usize, Option<usize>) {
377 let len = self.len();
378 (len, Some(len))
379 }
380
381 fn next(&mut self) -> Option<Self::Item> {
382 let i = self.i;
383 self.i = self.i.saturating_add(1);
384 if i >= self.len {
385 None
386 } else {
387 Some(unsafe { Robj::from_sexp(VECTOR_ELT(self.robj.get(), i as isize)) })
388 }
389 }
390
391 fn nth(&mut self, n: usize) -> Option<Self::Item> {
392 self.i = self.i.saturating_add(n);
393 self.next()
394 }
395}
396
397impl ExactSizeIterator for ListIter {
398 fn len(&self) -> usize {
400 self.len.saturating_sub(self.i)
401 }
402}
403
404pub struct FromList<T>(pub T);
414
415impl<T> TryFrom<&Robj> for FromList<Vec<T>>
416where
417 T: TryFrom<Robj>,
418 <T as TryFrom<Robj>>::Error: Into<Error>,
419{
420 type Error = Error;
421
422 fn try_from(robj: &Robj) -> Result<Self> {
423 let listiter: ListIter = robj.try_into()?;
424 let res: Result<Vec<_>> = listiter
425 .map(|robj| T::try_from(robj).map_err(|e| e.into()))
426 .collect();
427 res.map(FromList)
428 }
429}
430
431impl<T> TryFrom<Robj> for FromList<Vec<T>>
432where
433 T: TryFrom<Robj>,
434 <T as TryFrom<Robj>>::Error: Into<Error>,
435{
436 type Error = Error;
437
438 fn try_from(robj: Robj) -> Result<Self> {
439 <FromList<Vec<T>>>::try_from(&robj)
440 }
441}
442
443impl TryFrom<&Robj> for ListIter {
444 type Error = Error;
445
446 fn try_from(robj: &Robj) -> Result<Self> {
448 let list: List = robj.try_into()?;
449 Ok(list.values())
450 }
451}
452
453impl TryFrom<Robj> for ListIter {
454 type Error = Error;
455
456 fn try_from(robj: Robj) -> Result<Self> {
458 <ListIter>::try_from(&robj)
459 }
460}
461
462impl From<ListIter> for Robj {
463 fn from(iter: ListIter) -> Self {
472 iter.robj
473 }
474}
475
476pub trait KeyValue {
478 fn key(&self) -> String;
479 fn value(self) -> Robj;
480}
481
482impl<T: AsRef<str>> KeyValue for (T, Robj) {
483 fn key(&self) -> String {
484 self.0.as_ref().to_owned()
485 }
486 fn value(self) -> Robj {
487 self.1
488 }
489}
490
491impl<T: Into<Robj>> FromIterator<T> for List {
492 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
494 let iter_collect: Vec<_> = iter.into_iter().collect();
495 let len = iter_collect.len();
496
497 crate::single_threaded(|| unsafe {
498 let mut robj = Robj::alloc_vector(SEXPTYPE::VECSXP, len);
499 for (i, v) in iter_collect.into_iter().enumerate() {
500 let item: Robj = v.into();
506 SET_VECTOR_ELT(robj.get_mut(), i as isize, item.get());
507 }
508
509 List { robj }
510 })
511 }
512}
513
514impl Attributes for List {}
515
516impl Deref for List {
517 type Target = [Robj];
518
519 fn deref(&self) -> &Self::Target {
521 self.as_slice()
522 }
523}
524
525impl std::fmt::Debug for List {
526 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
527 if self.names().is_none() {
528 write!(
529 f,
530 "list!({})",
531 self.values()
532 .map(|v| format!("{:?}", v))
533 .collect::<Vec<_>>()
534 .join(", ")
535 )
536 } else {
537 write!(
538 f,
539 "list!({})",
540 self.iter()
541 .map(|(k, v)| if !k.is_empty() {
542 format!("{}={:?}", k, v)
543 } else {
544 format!("{:?}", v)
545 })
546 .collect::<Vec<_>>()
547 .join(", ")
548 )
549 }
550 }
551}