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 scope = crate::ProtectScope::new();
61 let list = scope.protect_raw(crate::sys::Rf_allocVector(crate::SEXPTYPE::VECSXP, n));
62
63 let names = scope.protect_raw(crate::sys::Rf_allocVector(crate::SEXPTYPE::STRSXP, n));
65
66 for (i, (key, value)) in iter.enumerate() {
67 let idx: crate::R_xlen_t = i.try_into().expect("index exceeds isize::MAX");
68 list.set_vector_elt(idx, value.into_sexp());
70
71 let charsxp = str_to_charsxp(&key);
73 names.set_string_elt(idx, charsxp);
74 }
75
76 list.set_names(names);
78
79 list
80 }
81}
82
83unsafe fn map_to_named_list_unchecked<V: IntoR>(
85 iter: impl ExactSizeIterator<Item = (String, V)>,
86) -> crate::SEXP {
87 unsafe {
88 let n: crate::R_xlen_t = iter
89 .len()
90 .try_into()
91 .expect("map length exceeds isize::MAX");
92 let scope = crate::ProtectScope::new();
93 let list = scope.protect_raw(crate::sys::Rf_allocVector_unchecked(
94 crate::SEXPTYPE::VECSXP,
95 n,
96 ));
97
98 let names = scope.protect_raw(crate::sys::Rf_allocVector_unchecked(
99 crate::SEXPTYPE::STRSXP,
100 n,
101 ));
102
103 for (i, (key, value)) in iter.enumerate() {
104 let idx: crate::R_xlen_t = i.try_into().expect("index exceeds isize::MAX");
105 list.set_vector_elt_unchecked(idx, value.into_sexp_unchecked());
106
107 let charsxp = str_to_charsxp_unchecked(&key);
108 names.set_string_elt_unchecked(idx, charsxp);
109 }
110
111 list.set_attr_unchecked(crate::SEXP::names_symbol(), names);
112
113 list
114 }
115}
116
117impl<T> IntoR for HashSet<T>
119where
120 T: crate::RNativeType + Eq + Hash,
121{
122 type Error = std::convert::Infallible;
123 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
124 Ok(self.into_sexp())
125 }
126 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
127 Ok(unsafe { self.into_sexp_unchecked() })
128 }
129 fn into_sexp(self) -> crate::SEXP {
130 let vec: Vec<T> = self.into_iter().collect();
131 vec.into_sexp()
132 }
133 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
134 let vec: Vec<T> = self.into_iter().collect();
135 unsafe { vec.into_sexp_unchecked() }
136 }
137}
138
139impl<T> IntoR for BTreeSet<T>
141where
142 T: crate::RNativeType + Ord,
143{
144 type Error = std::convert::Infallible;
145 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
146 Ok(self.into_sexp())
147 }
148 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
149 Ok(unsafe { self.into_sexp_unchecked() })
150 }
151 fn into_sexp(self) -> crate::SEXP {
152 let vec: Vec<T> = self.into_iter().collect();
153 vec.into_sexp()
154 }
155 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
156 let vec: Vec<T> = self.into_iter().collect();
157 unsafe { vec.into_sexp_unchecked() }
158 }
159}
160
161macro_rules! impl_set_string_into_r {
162 ($(#[$meta:meta])* $set_ty:ident) => {
163 $(#[$meta])*
164 impl IntoR for $set_ty<String> {
165 type Error = crate::into_r_error::IntoRError;
166 fn try_into_sexp(self) -> Result<crate::SEXP, Self::Error> {
167 Ok(self.into_sexp())
168 }
169 unsafe fn try_into_sexp_unchecked(self) -> Result<crate::SEXP, Self::Error> {
170 Ok(unsafe { self.into_sexp_unchecked() })
171 }
172 fn into_sexp(self) -> crate::SEXP {
173 let vec: Vec<String> = self.into_iter().collect();
174 vec.into_sexp()
175 }
176 unsafe fn into_sexp_unchecked(self) -> crate::SEXP {
177 let vec: Vec<String> = self.into_iter().collect();
178 unsafe { vec.into_sexp_unchecked() }
179 }
180 }
181 };
182}
183
184impl_set_string_into_r!(
185 HashSet
187);
188impl_set_string_into_r!(
189 BTreeSet
191);
192