miniextendr_api/into_r/
collections.rs1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
18use std::hash::Hash;
19
20use crate::SexpExt;
21use crate::into_r::{IntoR, str_to_charsxp, str_to_charsxp_unchecked};
22
23macro_rules! impl_map_into_r {
24 ($(#[$meta:meta])* $map_ty:ident) => {
25 $(#[$meta])*
26 impl<V: IntoR> IntoR for $map_ty<String, V> {
27 type Error = crate::into_r_error::IntoRError;
28 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
29 Ok(self.into_sexp())
30 }
31 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
32 Ok(unsafe { self.into_sexp_unchecked() })
33 }
34 fn into_sexp(self) -> crate::SEXP {
35 map_to_named_list(self.into_iter())
36 }
37 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
38 unsafe { map_to_named_list_unchecked(self.into_iter()) }
39 }
40 }
41 };
42}
43
44impl_map_into_r!(
45 HashMap
47);
48impl_map_into_r!(
49 BTreeMap
51);
52
53fn map_to_named_list<V: IntoR>(iter: impl ExactSizeIterator<Item = (String, V)>) -> crate::SEXP {
55 unsafe {
56 let n: crate::R_xlen_t = iter
57 .len()
58 .try_into()
59 .expect("map length exceeds isize::MAX");
60 let list = crate::sys::Rf_allocVector(crate::SEXPTYPE::VECSXP, n);
61 crate::sys::Rf_protect(list);
62
63 let names = crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP, n);
65 crate::sys::Rf_protect(names);
66
67 for (i, (key, value)) in iter.enumerate() {
68 let idx: crate::R_xlen_t = i.try_into().expect("index exceeds isize::MAX");
69 list.set_vector_elt(idx, value.into_sexp());
71
72 let charsxp = str_to_charsxp(&key);
74 names.set_string_elt(idx, charsxp);
75 }
76
77 list.set_names(names);
79
80 crate::sys::Rf_unprotect(2);
81 list
82 }
83}
84
85unsafe fn map_to_named_list_unchecked<V: IntoR>(
87 iter: impl ExactSizeIterator<Item = (String, V)>,
88) -> crate::SEXP {
89 unsafe {
90 let n: crate::R_xlen_t = iter
91 .len()
92 .try_into()
93 .expect("map length exceeds isize::MAX");
94 let list = crate::sys::Rf_allocVector_unchecked(crate::SEXPTYPE::VECSXP, n);
95 crate::sys::Rf_protect(list);
96
97 let names = crate::sys::Rf_allocVector_unchecked(crate::SEXPTYPE::STRSXP, n);
98 crate::sys::Rf_protect(names);
99
100 for (i, (key, value)) in iter.enumerate() {
101 let idx: crate::R_xlen_t = i.try_into().expect("index exceeds isize::MAX");
102 list.set_vector_elt_unchecked(idx, value.into_sexp_unchecked());
103
104 let charsxp = str_to_charsxp_unchecked(&key);
105 names.set_string_elt_unchecked(idx, charsxp);
106 }
107
108 list.set_attr_unchecked(crate::SEXP::names_symbol(), names);
109
110 crate::sys::Rf_unprotect(2);
111 list
112 }
113}
114
115impl<T> IntoR for HashSet<T>
117where
118 T: crate::RNativeType + Eq + Hash,
119{
120 type Error = std::convert::Infallible;
121 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
122 Ok(self.into_sexp())
123 }
124 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
125 Ok(unsafe { self.into_sexp_unchecked() })
126 }
127 fn into_sexp(self) -> crate::SEXP {
128 let vec: Vec<T> = self.into_iter().collect();
129 vec.into_sexp()
130 }
131 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
132 let vec: Vec<T> = self.into_iter().collect();
133 unsafe { vec.into_sexp_unchecked() }
134 }
135}
136
137impl<T> IntoR for BTreeSet<T>
139where
140 T: crate::RNativeType + Ord,
141{
142 type Error = std::convert::Infallible;
143 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
144 Ok(self.into_sexp())
145 }
146 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
147 Ok(unsafe { self.into_sexp_unchecked() })
148 }
149 fn into_sexp(self) -> crate::SEXP {
150 let vec: Vec<T> = self.into_iter().collect();
151 vec.into_sexp()
152 }
153 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
154 let vec: Vec<T> = self.into_iter().collect();
155 unsafe { vec.into_sexp_unchecked() }
156 }
157}
158
159macro_rules! impl_set_string_into_r {
160 ($(#[$meta:meta])* $set_ty:ident) => {
161 $(#[$meta])*
162 impl IntoR for $set_ty<String> {
163 type Error = crate::into_r_error::IntoRError;
164 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
165 Ok(self.into_sexp())
166 }
167 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
168 Ok(unsafe { self.into_sexp_unchecked() })
169 }
170 fn into_sexp(self) -> crate::SEXP {
171 let vec: Vec<String> = self.into_iter().collect();
172 vec.into_sexp()
173 }
174 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
175 let vec: Vec<String> = self.into_iter().collect();
176 unsafe { vec.into_sexp_unchecked() }
177 }
178 }
179 };
180}
181
182impl_set_string_into_r!(
183 HashSet
185);
186impl_set_string_into_r!(
187 BTreeSet
189);
190