1#![allow(rustdoc::private_intra_doc_links)]
2use crate::ffi::SEXPTYPE::{LISTSXP, STRSXP, VECSXP};
21use crate::ffi::{self, SEXP, SexpExt};
22use crate::from_r::{SexpError, SexpLengthError, SexpTypeError, TryFromSexp};
23use crate::gc_protect::OwnedProtect;
24use crate::into_r::IntoR;
25use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
26use std::hash::Hash;
27
28#[derive(Clone, Copy, Debug)]
40pub struct List(SEXP);
41
42#[derive(Debug)]
47pub struct ListMut(SEXP);
48
49impl List {
50 #[inline]
52 pub fn is_list(self) -> bool {
53 self.0.is_pair_list()
54 }
55
56 #[inline]
63 pub const unsafe fn from_raw(sexp: SEXP) -> Self {
64 List(sexp)
65 }
66
67 #[inline]
69 pub const fn as_sexp(self) -> SEXP {
70 self.0
71 }
72
73 #[inline]
75 pub fn len(self) -> isize {
76 self.0.xlength()
77 }
78
79 #[inline]
81 pub fn is_empty(self) -> bool {
82 self.len() == 0
83 }
84
85 #[inline]
87 pub fn get(self, idx: isize) -> Option<SEXP> {
88 if idx < 0 || idx >= self.len() {
89 return None;
90 }
91 Some(self.0.vector_elt(idx))
92 }
93
94 #[inline]
98 pub fn get_index<T>(self, idx: isize) -> Option<T>
99 where
100 T: TryFromSexp<Error = SexpError>,
101 {
102 let sexp = self.get(idx)?;
103 T::try_from_sexp(sexp).ok()
104 }
105
106 pub fn get_named<T>(self, name: &str) -> Option<T>
110 where
111 T: TryFromSexp<Error = SexpError>,
112 {
113 let names_sexp = self.names()?;
114 let n = self.len();
115
116 for i in 0..n {
118 let name_sexp = names_sexp.string_elt(i);
119 if name_sexp == SEXP::na_string() {
120 continue;
121 }
122 let name_ptr = name_sexp.r_char();
123 let name_cstr = unsafe { std::ffi::CStr::from_ptr(name_ptr) };
124 if let Ok(s) = name_cstr.to_str() {
125 if s == name {
126 let elem = self.0.vector_elt(i);
127 return T::try_from_sexp(elem).ok();
128 }
129 }
130 }
131 None
132 }
133
134 #[inline]
138 fn get_attr_opt(self, name: SEXP) -> Option<SEXP> {
139 let attr = self.0.get_attr(name);
140 if attr.is_nil() { None } else { Some(attr) }
141 }
142
143 #[inline]
145 pub fn names(self) -> Option<SEXP> {
146 self.get_attr_opt(SEXP::names_symbol())
147 }
148
149 #[inline]
151 pub fn get_class(self) -> Option<SEXP> {
152 self.get_attr_opt(SEXP::class_symbol())
153 }
154
155 #[inline]
157 pub fn get_dim(self) -> Option<SEXP> {
158 self.get_attr_opt(SEXP::dim_symbol())
159 }
160
161 #[inline]
163 pub fn get_dimnames(self) -> Option<SEXP> {
164 self.get_attr_opt(SEXP::dimnames_symbol())
165 }
166
167 #[inline]
169 pub fn get_rownames(self) -> Option<SEXP> {
170 let rownames = unsafe { ffi::Rf_GetRowNames(self.0) };
171 if rownames.is_nil() {
172 None
173 } else {
174 Some(rownames)
175 }
176 }
177
178 #[inline]
180 pub fn get_colnames(self) -> Option<SEXP> {
181 let dimnames = self.0.get_dimnames();
182 if dimnames.is_nil() {
183 return None;
184 }
185 let colnames = unsafe { ffi::Rf_GetColNames(dimnames) };
186 if colnames.is_nil() {
187 None
188 } else {
189 Some(colnames)
190 }
191 }
192
193 #[inline]
195 pub fn get_levels(self) -> Option<SEXP> {
196 self.get_attr_opt(SEXP::levels_symbol())
197 }
198
199 #[inline]
201 pub fn get_tsp(self) -> Option<SEXP> {
202 self.get_attr_opt(SEXP::tsp_symbol())
203 }
204 #[inline]
212 pub fn set_names(self, names: SEXP) -> Self {
213 self.0.set_names(names);
214 self
215 }
216
217 #[inline]
221 pub fn set_class(self, class: SEXP) -> Self {
222 self.0.set_class(class);
223 self
224 }
225
226 #[inline]
230 pub fn set_dim(self, dim: SEXP) -> Self {
231 self.0.set_dim(dim);
232 self
233 }
234
235 #[inline]
239 pub fn set_dimnames(self, dimnames: SEXP) -> Self {
240 self.0.set_dimnames(dimnames);
241 self
242 }
243
244 #[inline]
248 pub fn set_levels(self, levels: SEXP) -> Self {
249 self.0.set_levels(levels);
250 self
251 }
252 #[inline]
268 pub fn set_class_str(self, classes: &[&str]) -> Self {
269 use crate::ffi::SEXPTYPE::STRSXP;
270
271 let n: isize = classes
272 .len()
273 .try_into()
274 .expect("classes length exceeds isize::MAX");
275 unsafe {
276 let _self_guard = OwnedProtect::new(self.0);
280 let class_vec = OwnedProtect::new(ffi::Rf_allocVector(STRSXP, n));
281 for (i, class) in classes.iter().enumerate() {
282 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
283 class_vec.get().set_string_elt(idx, SEXP::charsxp(class));
284 }
285 self.0.set_class(class_vec.get());
286 }
287 self
288 }
289
290 #[inline]
294 pub fn set_data_frame_class(self) -> Self {
295 self.0
296 .set_class(crate::cached_class::data_frame_class_sexp());
297 self
298 }
299
300 #[inline]
312 pub fn set_names_str(self, names: &[&str]) -> Self {
313 use crate::ffi::SEXPTYPE::STRSXP;
314
315 let n: isize = names
316 .len()
317 .try_into()
318 .expect("names length exceeds isize::MAX");
319 unsafe {
320 let _self_guard = OwnedProtect::new(self.0);
322 let names_vec = OwnedProtect::new(ffi::Rf_allocVector(STRSXP, n));
323 for (i, name) in names.iter().enumerate() {
324 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
325 names_vec.get().set_string_elt(idx, SEXP::charsxp(name));
326 }
327 self.0.set_names(names_vec.get());
328 }
329 self
330 }
331
332 #[inline]
349 pub fn set_row_names_int(self, n: usize) -> Self {
350 unsafe {
351 let _self_guard = OwnedProtect::new(self.0);
353 let (row_names, rn) = crate::into_r::alloc_r_vector::<i32>(2);
355 let _guard = OwnedProtect::new(row_names);
356 rn[0] = i32::MIN; let n_i32 = i32::try_from(n).unwrap_or_else(|_| {
358 panic!("row count {n} exceeds i32::MAX");
359 });
360 rn[1] = -n_i32;
361 self.0.set_row_names(row_names);
362 }
363 self
364 }
365
366 #[inline]
381 pub fn set_row_names_str(self, row_names: &[&str]) -> Self {
382 use crate::ffi::SEXPTYPE::STRSXP;
383
384 let n: isize = row_names
385 .len()
386 .try_into()
387 .expect("row_names length exceeds isize::MAX");
388 unsafe {
389 let _self_guard = OwnedProtect::new(self.0);
391 let names_vec = OwnedProtect::new(ffi::Rf_allocVector(STRSXP, n));
392 for (i, name) in row_names.iter().enumerate() {
393 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
394 names_vec.get().set_string_elt(idx, SEXP::charsxp(name));
395 }
396 self.0.set_row_names(names_vec.get());
397 }
398 self
399 }
400 #[inline]
432 pub unsafe fn set_elt(self, idx: isize, child: SEXP) {
433 assert!(idx >= 0 && idx < self.len(), "index out of bounds");
434 unsafe {
438 let _guard = OwnedProtect::new(child);
439 self.0.set_vector_elt(idx, child);
440 }
441 }
442
443 #[inline]
455 pub unsafe fn set_elt_unchecked(self, idx: isize, child: SEXP) {
456 debug_assert!(idx >= 0 && idx < self.len(), "index out of bounds");
457 self.0.set_vector_elt(idx, child);
459 }
460
461 #[inline]
485 pub unsafe fn set_elt_with<F>(self, idx: isize, f: F)
486 where
487 F: FnOnce() -> SEXP,
488 {
489 assert!(idx >= 0 && idx < self.len(), "index out of bounds");
490 unsafe {
492 let child = OwnedProtect::new(f());
493 self.0.set_vector_elt(idx, child.get());
494 }
495 }
496 }
498
499use crate::gc_protect::ProtectScope;
502
503pub struct ListBuilder<'a> {
526 list: SEXP,
527 _scope: &'a ProtectScope,
528}
529
530impl<'a> ListBuilder<'a> {
531 #[inline]
539 pub unsafe fn new(scope: &'a ProtectScope, len: usize) -> Self {
540 let list = unsafe { scope.alloc_vecsxp(len).into_raw() };
542 Self {
543 list,
544 _scope: scope,
545 }
546 }
547
548 #[inline]
555 pub unsafe fn from_protected(scope: &'a ProtectScope, list: SEXP) -> Self {
556 Self {
557 list,
558 _scope: scope,
559 }
560 }
561
562 #[inline]
572 pub unsafe fn set(&self, idx: isize, child: SEXP) {
573 debug_assert!(idx >= 0 && idx < self.list.xlength());
575 self.list.set_vector_elt(idx, child);
576 }
577
578 #[inline]
586 pub unsafe fn set_protected(&self, idx: isize, child: SEXP) {
587 unsafe {
589 debug_assert!(idx >= 0 && idx < self.list.xlength());
590 let _guard = OwnedProtect::new(child);
591 self.list.set_vector_elt(idx, child);
592 }
593 }
594
595 #[inline]
597 pub fn as_sexp(&self) -> SEXP {
598 self.list
599 }
600
601 #[inline]
603 pub fn into_list(self) -> List {
604 List(self.list)
605 }
606
607 #[inline]
609 pub fn into_sexp(self) -> SEXP {
610 self.list
611 }
612
613 #[inline]
615 pub fn len(&self) -> isize {
616 self.list.xlength()
617 }
618
619 #[inline]
621 pub fn is_empty(&self) -> bool {
622 self.len() == 0
623 }
624}
625mod accumulator;
628mod named;
629
630pub use accumulator::*;
631pub use named::*;
632
633pub trait IntoList {
637 fn into_list(self) -> List;
639}
640
641pub trait TryFromList: Sized {
643 type Error;
645
646 fn try_from_list(list: List) -> Result<Self, Self::Error>;
648}
649
650impl<T: IntoR> IntoList for Vec<T> {
651 fn into_list(self) -> List {
652 let n: isize = self
657 .len()
658 .try_into()
659 .expect("list length exceeds isize::MAX");
660 unsafe {
661 let list = OwnedProtect::new(ffi::Rf_allocVector(VECSXP, n));
662 for (i, val) in self.into_iter().enumerate() {
663 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
664 list.get().set_vector_elt(idx, val.into_sexp());
665 }
666 List(list.get())
667 }
668 }
669}
670
671impl<T> TryFromList for Vec<T>
672where
673 T: TryFromSexp<Error = SexpError>,
674{
675 type Error = SexpError;
676
677 fn try_from_list(list: List) -> Result<Self, Self::Error> {
678 let expected: usize = list
679 .len()
680 .try_into()
681 .expect("list length must be non-negative");
682 let mut out = Vec::with_capacity(expected);
683 for i in 0..expected {
684 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
685 let sexp = list.get(idx).ok_or_else(|| {
686 SexpError::from(SexpLengthError {
687 expected,
688 actual: i,
689 })
690 })?;
691 out.push(TryFromSexp::try_from_sexp(sexp)?);
692 }
693 Ok(out)
694 }
695}
696
697impl<K, V> IntoList for HashMap<K, V>
702where
703 K: AsRef<str>,
704 V: IntoR,
705{
706 fn into_list(self) -> List {
707 let pairs: Vec<(K, V)> = self.into_iter().collect();
708 List::from_pairs(pairs)
709 }
710}
711
712impl<V> TryFromList for HashMap<String, V>
713where
714 V: TryFromSexp<Error = SexpError>,
715{
716 type Error = SexpError;
717
718 fn try_from_list(list: List) -> Result<Self, Self::Error> {
719 let n: usize = list
720 .len()
721 .try_into()
722 .expect("list length must be non-negative");
723 let names_sexp = list.names();
724 let mut map = HashMap::with_capacity(n);
725
726 for i in 0..n {
727 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
728 let sexp = list.get(idx).ok_or_else(|| {
729 SexpError::from(SexpLengthError {
730 expected: n,
731 actual: i,
732 })
733 })?;
734 let value: V = TryFromSexp::try_from_sexp(sexp)?;
735
736 let key = if let Some(names) = names_sexp {
737 let name_sexp = names.string_elt(idx);
738 if name_sexp == SEXP::na_string() {
739 format!("{i}")
740 } else {
741 let name_ptr = name_sexp.r_char();
742 let name_cstr = unsafe { std::ffi::CStr::from_ptr(name_ptr) };
743 name_cstr.to_str().unwrap_or(&format!("{i}")).to_string()
744 }
745 } else {
746 format!("{i}")
747 };
748
749 map.insert(key, value);
750 }
751 Ok(map)
752 }
753}
754impl<K, V> IntoList for BTreeMap<K, V>
759where
760 K: AsRef<str>,
761 V: IntoR,
762{
763 fn into_list(self) -> List {
764 let pairs: Vec<(K, V)> = self.into_iter().collect();
765 List::from_pairs(pairs)
766 }
767}
768
769impl<V> TryFromList for BTreeMap<String, V>
770where
771 V: TryFromSexp<Error = SexpError>,
772{
773 type Error = SexpError;
774
775 fn try_from_list(list: List) -> Result<Self, Self::Error> {
776 let n: usize = list
777 .len()
778 .try_into()
779 .expect("list length must be non-negative");
780 let names_sexp = list.names();
781 let mut map = BTreeMap::new();
782
783 for i in 0..n {
784 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
785 let sexp = list.get(idx).ok_or_else(|| {
786 SexpError::from(SexpLengthError {
787 expected: n,
788 actual: i,
789 })
790 })?;
791 let value: V = TryFromSexp::try_from_sexp(sexp)?;
792
793 let key = if let Some(names) = names_sexp {
794 let name_sexp = names.string_elt(idx);
795 if name_sexp == SEXP::na_string() {
796 format!("{i}")
797 } else {
798 let name_ptr = name_sexp.r_char();
799 let name_cstr = unsafe { std::ffi::CStr::from_ptr(name_ptr) };
800 name_cstr.to_str().unwrap_or(&format!("{i}")).to_string()
801 }
802 } else {
803 format!("{i}")
804 };
805
806 map.insert(key, value);
807 }
808 Ok(map)
809 }
810}
811impl<T> IntoList for HashSet<T>
816where
817 T: IntoR,
818{
819 fn into_list(self) -> List {
820 let values: Vec<T> = self.into_iter().collect();
821 values.into_list()
822 }
823}
824
825impl<T> TryFromList for HashSet<T>
826where
827 T: TryFromSexp<Error = SexpError> + Eq + Hash,
828{
829 type Error = SexpError;
830
831 fn try_from_list(list: List) -> Result<Self, Self::Error> {
832 let vec: Vec<T> = TryFromList::try_from_list(list)?;
833 Ok(vec.into_iter().collect())
834 }
835}
836impl<T> IntoList for BTreeSet<T>
841where
842 T: IntoR,
843{
844 fn into_list(self) -> List {
845 let values: Vec<T> = self.into_iter().collect();
846 values.into_list()
847 }
848}
849
850impl<T> TryFromList for BTreeSet<T>
851where
852 T: TryFromSexp<Error = SexpError> + Ord,
853{
854 type Error = SexpError;
855
856 fn try_from_list(list: List) -> Result<Self, Self::Error> {
857 let vec: Vec<T> = TryFromList::try_from_list(list)?;
858 Ok(vec.into_iter().collect())
859 }
860}
861
862impl List {
863 pub fn from_pairs<N, T>(pairs: Vec<(N, T)>) -> Self
865 where
866 N: AsRef<str>,
867 T: IntoR,
868 {
869 let n: isize = pairs
874 .len()
875 .try_into()
876 .expect("pairs length exceeds isize::MAX");
877 unsafe {
878 let list = OwnedProtect::new(ffi::Rf_allocVector(VECSXP, n));
879 let names = OwnedProtect::new(ffi::Rf_allocVector(STRSXP, n));
880 for (i, (name, val)) in pairs.into_iter().enumerate() {
881 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
882 list.get().set_vector_elt(idx, val.into_sexp());
883 names
884 .get()
885 .set_string_elt(idx, SEXP::charsxp(name.as_ref()));
886 }
887 list.get().set_names(names.get());
888 List(list.get())
889 }
890 }
891
892 pub fn from_values<T: IntoR>(values: Vec<T>) -> Self {
903 values.into_list()
904 }
905
906 pub fn from_raw_values(values: Vec<SEXP>) -> Self {
913 let n: isize = values
914 .len()
915 .try_into()
916 .expect("values length exceeds isize::MAX");
917 unsafe {
918 let list = OwnedProtect::new(ffi::Rf_allocVector(VECSXP, n));
921 for (i, val) in values.into_iter().enumerate() {
922 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
923 list.get().set_vector_elt(idx, val);
924 }
925 List(list.get())
926 }
927 }
928
929 pub fn from_scalars_or_list(elements: &[SEXP]) -> Self {
943 use crate::ffi::SEXPTYPE;
944 use crate::into_r::alloc_r_vector;
945
946 if elements.is_empty() {
947 return Self::from_raw_values(Vec::new());
948 }
949
950 let first_type = elements[0].type_of();
951 let all_scalar_same_type = elements
952 .iter()
953 .all(|&e| e.xlength() == 1 && e.type_of() == first_type);
954
955 if !all_scalar_same_type {
956 return Self::from_raw_values(elements.to_vec());
957 }
958
959 let n = elements.len();
960 let sexp = match first_type {
961 SEXPTYPE::INTSXP => unsafe {
964 let (v, dst) = alloc_r_vector::<i32>(n);
965 for (slot, &elem) in dst.iter_mut().zip(elements.iter()) {
966 *slot = *elem.as_slice::<i32>().first().expect("scalar has length 1");
967 }
968 v
969 },
970 SEXPTYPE::REALSXP => unsafe {
971 let (v, dst) = alloc_r_vector::<f64>(n);
972 for (slot, &elem) in dst.iter_mut().zip(elements.iter()) {
973 *slot = *elem.as_slice::<f64>().first().expect("scalar has length 1");
974 }
975 v
976 },
977 SEXPTYPE::LGLSXP => unsafe {
978 let (v, dst) = alloc_r_vector::<crate::ffi::RLogical>(n);
979 for (slot, &elem) in dst.iter_mut().zip(elements.iter()) {
980 *slot = *elem
981 .as_slice::<crate::ffi::RLogical>()
982 .first()
983 .expect("scalar has length 1");
984 }
985 v
986 },
987 SEXPTYPE::STRSXP => unsafe {
989 let v = OwnedProtect::new(ffi::Rf_allocVector(SEXPTYPE::STRSXP, n as isize));
990 for (i, &elem) in elements.iter().enumerate() {
991 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
992 v.get().set_string_elt(idx, elem.string_elt(0));
993 }
994 v.get()
995 },
996 _ => return Self::from_raw_values(elements.to_vec()),
997 };
998 List(sexp)
999 }
1000
1001 pub fn from_raw_pairs<N>(pairs: Vec<(N, SEXP)>) -> Self
1009 where
1010 N: AsRef<str>,
1011 {
1012 let n: isize = pairs
1013 .len()
1014 .try_into()
1015 .expect("pairs length exceeds isize::MAX");
1016 unsafe {
1017 let list = OwnedProtect::new(ffi::Rf_allocVector(VECSXP, n));
1020 let names = OwnedProtect::new(ffi::Rf_allocVector(STRSXP, n));
1021 for (i, (name, val)) in pairs.into_iter().enumerate() {
1022 let idx: isize = i.try_into().expect("index exceeds isize::MAX");
1023 list.get().set_vector_elt(idx, val);
1024
1025 let s = name.as_ref();
1026 names.get().set_string_elt(idx, SEXP::charsxp(s));
1028 }
1029 list.get().set_names(names.get());
1030 List(list.get())
1031 }
1032 }
1033
1034 #[must_use]
1045 pub fn from_raw_pairs_empty() -> Self {
1046 Self::from_raw_pairs(Vec::<(&str, SEXP)>::new())
1047 }
1048}
1049
1050impl IntoR for List {
1051 type Error = std::convert::Infallible;
1052 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
1053 Ok(self.into_sexp())
1054 }
1055 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
1056 self.try_into_sexp()
1057 }
1058 #[inline]
1059 fn into_sexp(self) -> SEXP {
1060 self.0
1061 }
1062}
1063
1064impl IntoR for ListMut {
1065 type Error = std::convert::Infallible;
1066 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
1067 Ok(self.into_sexp())
1068 }
1069 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
1070 self.try_into_sexp()
1071 }
1072 #[inline]
1073 fn into_sexp(self) -> SEXP {
1074 self.0
1075 }
1076}
1077
1078impl IntoR for Vec<List> {
1084 type Error = std::convert::Infallible;
1085 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
1086 Ok(self.into_sexp())
1087 }
1088 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
1089 self.try_into_sexp()
1090 }
1091 fn into_sexp(self) -> SEXP {
1092 unsafe {
1093 use crate::ffi::{Rf_allocVector, Rf_protect, Rf_unprotect, SEXPTYPE, SexpExt as _};
1094 let n = self.len() as crate::ffi::R_xlen_t;
1095 let out = Rf_allocVector(SEXPTYPE::VECSXP, n);
1096 Rf_protect(out);
1097 for (i, list) in self.into_iter().enumerate() {
1098 out.set_vector_elt(i as crate::ffi::R_xlen_t, list.0);
1099 }
1100 Rf_unprotect(1);
1101 out
1102 }
1103 }
1104}
1105
1106impl IntoR for Vec<Option<List>> {
1112 type Error = std::convert::Infallible;
1113 fn try_into_sexp(self) -> Result<SEXP, Self::Error> {
1114 Ok(self.into_sexp())
1115 }
1116 unsafe fn try_into_sexp_unchecked(self) -> Result<SEXP, Self::Error> {
1117 self.try_into_sexp()
1118 }
1119 fn into_sexp(self) -> SEXP {
1120 unsafe {
1121 use crate::ffi::{Rf_allocVector, Rf_protect, Rf_unprotect, SEXPTYPE, SexpExt as _};
1122 let n = self.len() as crate::ffi::R_xlen_t;
1123 let out = Rf_allocVector(SEXPTYPE::VECSXP, n);
1126 Rf_protect(out);
1127 for (i, opt) in self.into_iter().enumerate() {
1128 if let Some(list) = opt {
1129 out.set_vector_elt(i as crate::ffi::R_xlen_t, list.0);
1130 }
1131 }
1132 Rf_unprotect(1);
1133 out
1134 }
1135 }
1136}
1137
1138#[derive(Debug, Clone)]
1140pub struct DuplicateNameError {
1141 pub name: String,
1143}
1144
1145impl std::fmt::Display for DuplicateNameError {
1146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1147 write!(f, "list has duplicate name: {:?}", self.name)
1148 }
1149}
1150
1151impl std::error::Error for DuplicateNameError {}
1152
1153#[derive(Debug, Clone)]
1155pub enum ListFromSexpError {
1156 Type(crate::from_r::SexpTypeError),
1158 DuplicateName(DuplicateNameError),
1160}
1161
1162impl std::fmt::Display for ListFromSexpError {
1163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1164 match self {
1165 ListFromSexpError::Type(e) => write!(f, "{}", e),
1166 ListFromSexpError::DuplicateName(e) => write!(f, "{}", e),
1167 }
1168 }
1169}
1170
1171impl std::error::Error for ListFromSexpError {}
1172
1173impl From<crate::from_r::SexpTypeError> for ListFromSexpError {
1174 fn from(e: crate::from_r::SexpTypeError) -> Self {
1175 ListFromSexpError::Type(e)
1176 }
1177}
1178
1179impl TryFromSexp for List {
1180 type Error = ListFromSexpError;
1181
1182 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1183 let actual = sexp.type_of();
1184
1185 let list_sexp = if actual == VECSXP {
1189 sexp
1190 } else if actual == LISTSXP {
1191 sexp.coerce(VECSXP)
1193 } else {
1194 return Err(crate::from_r::SexpTypeError {
1195 expected: VECSXP,
1196 actual,
1197 }
1198 .into());
1199 };
1200
1201 let names_sexp = list_sexp.get_names();
1203 if names_sexp != SEXP::nil() {
1204 let n = list_sexp.xlength();
1205 let n_usize: usize = n.try_into().expect("list length must be non-negative");
1206 let mut seen = HashSet::with_capacity(n_usize);
1207
1208 for i in 0..n {
1209 let name_sexp = names_sexp.string_elt(i);
1210 if name_sexp == SEXP::na_string() {
1212 continue;
1213 }
1214 let name_ptr = name_sexp.r_char();
1216 let name_cstr = unsafe { std::ffi::CStr::from_ptr(name_ptr) };
1217 if let Ok(s) = name_cstr.to_str() {
1218 if s.is_empty() {
1219 continue;
1220 }
1221 if !seen.insert(s) {
1222 return Err(ListFromSexpError::DuplicateName(DuplicateNameError {
1223 name: s.to_string(),
1224 }));
1225 }
1226 }
1227 }
1228 }
1229
1230 Ok(List(list_sexp))
1231 }
1232}
1233
1234impl TryFromSexp for Option<List> {
1235 type Error = SexpError;
1236
1237 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1238 if sexp == SEXP::nil() {
1239 return Ok(None);
1240 }
1241 let list = List::try_from_sexp(sexp).map_err(|e| SexpError::InvalidValue(e.to_string()))?;
1242 Ok(Some(list))
1243 }
1244}
1245
1246impl TryFromSexp for Option<ListMut> {
1247 type Error = SexpError;
1248
1249 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1250 if sexp == SEXP::nil() {
1251 return Ok(None);
1252 }
1253 let list = ListMut::try_from_sexp(sexp)?;
1254 Ok(Some(list))
1255 }
1256}
1257
1258impl TryFromSexp for ListMut {
1259 type Error = SexpError;
1260
1261 fn try_from_sexp(sexp: SEXP) -> Result<Self, Self::Error> {
1262 let actual = sexp.type_of();
1263 if actual != VECSXP {
1264 return Err(SexpTypeError {
1265 expected: VECSXP,
1266 actual,
1267 }
1268 .into());
1269 }
1270 Ok(ListMut(sexp))
1271 }
1272}
1273