aorist_extendr_api/wrapper/
symbol.rs

1use super::*;
2
3/// Wrapper for creating symbol objects.
4///
5/// ```
6/// use extendr_api::prelude::*;
7/// test! {
8///     let chr = r!(Symbol::from_string("xyz"));
9///     assert_eq!(chr.as_symbol().unwrap().as_str(), "xyz");
10/// }
11/// ```
12///
13#[derive(Debug, PartialEq, Clone)]
14pub struct Symbol {
15    pub(crate) robj: Robj,
16}
17
18impl Symbol {
19    /// Make a symbol object from a string.
20    ///
21    /// ```
22    /// use extendr_api::prelude::*;
23    /// test! {
24    ///     let chr = r!(Symbol::from_string("xyz"));
25    ///     assert_eq!(chr, sym!(xyz));
26    /// }
27    /// ```
28    pub fn from_string<S: AsRef<str>>(val: S) -> Self {
29        let val = val.as_ref();
30        Symbol {
31            robj: unsafe { new_owned(make_symbol(val)) },
32        }
33    }
34
35    // Internal conversion for constant symbols.
36    fn from_sexp(sexp: SEXP) -> Symbol {
37        unsafe {
38            assert!(TYPEOF(sexp) == SYMSXP as i32);
39        }
40        Symbol {
41            robj: unsafe { new_sys(sexp) },
42        }
43    }
44
45    /// Get the string from a symbol object.
46    /// ```
47    /// use extendr_api::prelude::*;
48    /// test! {
49    ///     assert_eq!(sym!(xyz).as_symbol().unwrap().as_str(), "xyz");
50    /// }
51    /// ```
52    pub fn as_str(&self) -> &str {
53        unsafe {
54            let sexp = self.robj.get();
55            let printname = PRINTNAME(sexp);
56            assert!(TYPEOF(printname) as u32 == CHARSXP);
57            to_str(R_CHAR(printname) as *const u8)
58        }
59    }
60}
61
62impl From<&str> for Symbol {
63    /// Convert a string to a symbol.
64    fn from(name: &str) -> Self {
65        Symbol::from_string(name)
66    }
67}
68
69/// Unbound marker
70pub fn unbound_value() -> Symbol {
71    unsafe { Symbol::from_sexp(R_UnboundValue) }
72}
73
74/// Missing argument marker
75pub fn missing_arg() -> Symbol {
76    unsafe { Symbol::from_sexp(R_MissingArg) }
77}
78
79/// "base"
80pub fn base_symbol() -> Symbol {
81    unsafe { Symbol::from_sexp(R_BaseSymbol) }
82}
83
84/// "{"
85pub fn brace_symbol() -> Symbol {
86    unsafe { Symbol::from_sexp(R_BraceSymbol) }
87}
88
89/// "[["
90pub fn bracket_2_symbol() -> Symbol {
91    unsafe { Symbol::from_sexp(R_Bracket2Symbol) }
92}
93
94/// "["
95pub fn bracket_symbol() -> Symbol {
96    unsafe { Symbol::from_sexp(R_BracketSymbol) }
97}
98
99/// "class"
100pub fn class_symbol() -> Symbol {
101    unsafe { Symbol::from_sexp(R_ClassSymbol) }
102}
103
104/// ".Device"
105pub fn device_symbol() -> Symbol {
106    unsafe { Symbol::from_sexp(R_DeviceSymbol) }
107}
108
109/// "dimnames"
110pub fn dimnames_symbol() -> Symbol {
111    unsafe { Symbol::from_sexp(R_DimNamesSymbol) }
112}
113
114/// "dim"
115pub fn dim_symbol() -> Symbol {
116    unsafe { Symbol::from_sexp(R_DimSymbol) }
117}
118
119/// "$"
120pub fn dollar_symbol() -> Symbol {
121    unsafe { Symbol::from_sexp(R_DollarSymbol) }
122}
123
124/// "..."
125pub fn dots_symbol() -> Symbol {
126    unsafe { Symbol::from_sexp(R_DotsSymbol) }
127}
128//     pub fn drop_symbol() -> Symbol { unsafe { Symbol::from_sexp(R_DropSymbol) }}"drop"
129
130/// "::"
131pub fn double_colon_symbol() -> Symbol {
132    unsafe { Symbol::from_sexp(R_DoubleColonSymbol) }
133}
134
135/// ".Last.value"
136pub fn lastvalue_symbol() -> Symbol {
137    unsafe { Symbol::from_sexp(R_LastvalueSymbol) }
138}
139/// "levels"
140pub fn levels_symbol() -> Symbol {
141    unsafe { Symbol::from_sexp(R_LevelsSymbol) }
142}
143/// "mode"
144pub fn mode_symbol() -> Symbol {
145    unsafe { Symbol::from_sexp(R_ModeSymbol) }
146}
147/// "na.rm"
148pub fn na_rm_symbol() -> Symbol {
149    unsafe { Symbol::from_sexp(R_NaRmSymbol) }
150}
151/// "name"
152pub fn name_symbol() -> Symbol {
153    unsafe { Symbol::from_sexp(R_NameSymbol) }
154}
155/// "names"
156pub fn names_symbol() -> Symbol {
157    unsafe { Symbol::from_sexp(R_NamesSymbol) }
158}
159/// _NAMESPACE__."
160pub fn namespace_env_symbol() -> Symbol {
161    unsafe { Symbol::from_sexp(R_NamespaceEnvSymbol) }
162}
163/// "package"
164pub fn package_symbol() -> Symbol {
165    unsafe { Symbol::from_sexp(R_PackageSymbol) }
166}
167/// "previous"
168pub fn previous_symbol() -> Symbol {
169    unsafe { Symbol::from_sexp(R_PreviousSymbol) }
170}
171/// "quote"
172pub fn quote_symbol() -> Symbol {
173    unsafe { Symbol::from_sexp(R_QuoteSymbol) }
174}
175/// "row.names"
176pub fn row_names_symbol() -> Symbol {
177    unsafe { Symbol::from_sexp(R_RowNamesSymbol) }
178}
179/// ".Random.seed"
180pub fn seeds_symbol() -> Symbol {
181    unsafe { Symbol::from_sexp(R_SeedsSymbol) }
182}
183/// "sort.list"
184pub fn sort_list_symbol() -> Symbol {
185    unsafe { Symbol::from_sexp(R_SortListSymbol) }
186}
187/// "source"
188pub fn source_symbol() -> Symbol {
189    unsafe { Symbol::from_sexp(R_SourceSymbol) }
190}
191/// "spec"
192pub fn spec_symbol() -> Symbol {
193    unsafe { Symbol::from_sexp(R_SpecSymbol) }
194}
195/// "tsp"
196pub fn tsp_symbol() -> Symbol {
197    unsafe { Symbol::from_sexp(R_TspSymbol) }
198}
199/// ":::"
200pub fn triple_colon_symbol() -> Symbol {
201    unsafe { Symbol::from_sexp(R_TripleColonSymbol) }
202}
203/// ".defined"
204pub fn dot_defined() -> Symbol {
205    unsafe { Symbol::from_sexp(R_dot_defined) }
206}
207/// ".Method"
208pub fn dot_method() -> Symbol {
209    unsafe { Symbol::from_sexp(R_dot_Method) }
210}
211/// "packageName"
212pub fn dot_package_name() -> Symbol {
213    unsafe { Symbol::from_sexp(R_dot_packageName) }
214}
215
216/// ".target"
217pub fn dot_target() -> Symbol {
218    unsafe { Symbol::from_sexp(R_dot_target) }
219}
220
221#[cfg(test)]
222mod test {
223    use super::*;
224
225    #[test]
226    fn test_constant_symbols() {
227        test! {
228            assert!(unbound_value().is_symbol());
229            assert!(missing_arg().is_symbol());
230            assert!(base_symbol().is_symbol());
231            assert!(brace_symbol().is_symbol());
232            assert!(bracket_2_symbol().is_symbol());
233            assert!(bracket_symbol().is_symbol());
234            assert!(class_symbol().is_symbol());
235            assert!(device_symbol().is_symbol());
236            assert!(dimnames_symbol().is_symbol());
237            assert!(dim_symbol().is_symbol());
238            assert!(dollar_symbol().is_symbol());
239            assert!(dots_symbol().is_symbol());
240            assert!(lastvalue_symbol().is_symbol());
241            assert!(levels_symbol().is_symbol());
242            assert!(mode_symbol().is_symbol());
243            assert!(na_rm_symbol().is_symbol());
244            assert!(name_symbol().is_symbol());
245            assert!(names_symbol().is_symbol());
246            assert!(namespace_env_symbol().is_symbol());
247            assert!(package_symbol().is_symbol());
248            assert!(previous_symbol().is_symbol());
249            assert!(quote_symbol().is_symbol());
250            assert!(row_names_symbol().is_symbol());
251            assert!(seeds_symbol().is_symbol());
252            assert!(sort_list_symbol().is_symbol());
253            assert!(source_symbol().is_symbol());
254            assert!(spec_symbol().is_symbol());
255            assert!(tsp_symbol().is_symbol());
256            assert!(triple_colon_symbol().is_symbol());
257            assert!(dot_defined().is_symbol());
258            assert!(dot_method().is_symbol());
259            assert!(dot_package_name().is_symbol());
260            assert!(dot_target().is_symbol());
261        }
262    }
263}