1mod altrep;
160mod c_wrapper_builder;
161mod call_method_def;
162mod cfg_gates;
163mod deprecation;
164mod dots_policy;
165mod externalptr_args;
166mod list_macro;
167mod match_arg_keys;
168mod miniextendr_fn;
169mod receiver_body;
170mod return_wrap;
171mod s7_conversion;
172mod trait_receiver;
173mod trait_self_ref;
174mod trait_signature;
175mod type_inspect;
176mod typed_dataframe;
177mod typed_list;
178mod util;
179use crate::miniextendr_fn::{MiniextendrFnAttrs, MiniextendrFunctionParsed};
180mod miniextendr_impl;
181mod r_wrapper_builder;
182pub(crate) use r_wrapper_builder::RArgumentBuilder;
184mod rust_conversion_builder;
185pub(crate) use rust_conversion_builder::RustConversionBuilder;
187mod method_return_builder;
188pub(crate) use method_return_builder::{MethodReturnBuilder, ReturnStrategy};
190mod altrep_derive;
191mod condition_derive;
192mod dataframe_derive;
193mod lifecycle;
194mod list_derive;
195mod r_class_formatter;
196mod r_preconditions;
197mod r_shadowing;
198mod return_type_analysis;
199mod roxygen;
200
201mod all_equal_derive;
203mod externalptr_derive;
204mod miniextendr_impl_trait;
205mod miniextendr_trait;
206mod typed_external_macro;
207
208mod factor_derive;
210mod match_arg_derive;
211mod newtype_derive;
212
213mod struct_enum_dispatch;
215mod misplaced_dots;
217
218mod r_macro;
220
221mod reexport;
223
224#[cfg(feature = "vctrs")]
226mod vctrs_derive;
227mod vctrs_generics;
228
229mod crate_config;
230mod naming;
231pub(crate) use naming::r_wrapper_const_ident_for;
232
233#[cfg(all(feature = "r6-default", feature = "s7-default"))]
235compile_error!(
236 "features \"r6-default\" and \"s7-default\" are mutually exclusive — \
237 enable exactly one, or omit both to fall back to the unspecified default"
238);
239pub(crate) use type_inspect::{
243 SeveralOkContainer, classify_several_ok_container, first_type_argument,
244 is_main_thread_bound_input, is_main_thread_bound_return, is_sexp_type, match_arg_choices_ty,
245 second_type_argument,
246};
247pub(crate) use util::{extract_cfg_attrs, r_wrapper_raw_literal, source_location_doc};
248
249fn validate_extern_signature(
259 abi: &syn::Abi,
260 attrs: &[syn::Attribute],
261 inputs: &syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]>,
262 output: &syn::ReturnType,
263) -> syn::Result<()> {
264 use syn::spanned::Spanned;
265
266 for input in inputs.iter() {
270 if let syn::FnArg::Receiver(recv) = input {
271 return Err(syn::Error::new_spanned(
272 recv,
273 "self parameter not allowed in standalone functions; \
274 use #[miniextendr(env|r6|s3|s4|s7)] on impl blocks instead",
275 ));
276 }
277 }
278
279 let has_no_mangle = attrs.iter().any(|attr| {
281 attr.path().is_ident("no_mangle")
282 || attr
283 .parse_nested_meta(|meta| {
284 if meta.path.is_ident("no_mangle") {
285 Err(meta.error("found #[no_mangle]"))
286 } else {
287 Ok(())
288 }
289 })
290 .is_err()
291 });
292 let has_export_name = attrs.iter().any(|attr| attr.path().is_ident("export_name"));
293 if !has_no_mangle && !has_export_name {
294 return Err(syn::Error::new(
295 attrs
296 .first()
297 .map(|attr| attr.span())
298 .unwrap_or_else(|| abi.span()),
299 "extern \"C-unwind\" functions need a visible C symbol for R's .Call interface. \
300 Add one of:\n \
301 - `#[unsafe(no_mangle)]` (Rust 2024 edition)\n \
302 - `#[no_mangle]` (Rust 2021 edition)\n \
303 - `#[export_name = \"my_symbol\"]` (custom symbol name)",
304 ));
305 }
306
307 match output {
309 non_return_type @ syn::ReturnType::Default => {
310 return Err(syn::Error::new(
311 non_return_type.span(),
312 "extern \"C-unwind\" functions used with #[miniextendr] must return SEXP. \
313 Add `-> miniextendr_api::SEXP` as the return type. \
314 If you want automatic type conversion, remove `extern \"C-unwind\"` and let \
315 the macro generate the C wrapper.",
316 ));
317 }
318 syn::ReturnType::Type(_rarrow, output_type) => match output_type.as_ref() {
319 syn::Type::Path(type_path) => {
320 if let Some(path_to_sexp) = type_path.path.segments.last().map(|x| &x.ident)
321 && path_to_sexp != "SEXP"
322 {
323 return Err(syn::Error::new(
324 path_to_sexp.span(),
325 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern \"C-unwind\" functions must return SEXP, found `{0}`. R\'s .Call interface expects SEXP return values. Change the return type to `miniextendr_api::SEXP`, or remove `extern \"C-unwind\"` to let the macro handle type conversion.",
path_to_sexp))
})format!(
326 "extern \"C-unwind\" functions must return SEXP, found `{path_to_sexp}`. \
327 R's .Call interface expects SEXP return values. \
328 Change the return type to `miniextendr_api::SEXP`, or remove \
329 `extern \"C-unwind\"` to let the macro handle type conversion.",
330 ),
331 ));
332 }
333 }
334 _ => {
335 return Err(syn::Error::new(
336 output_type.span(),
337 "extern \"C-unwind\" functions must return SEXP. \
338 R's .Call interface expects SEXP return values. \
339 Change the return type to `miniextendr_api::SEXP`, or remove \
340 `extern \"C-unwind\"` to let the macro handle type conversion.",
341 ));
342 }
343 },
344 }
345
346 for input in inputs.iter() {
348 match input {
349 syn::FnArg::Receiver(recv) => {
350 return Err(syn::Error::new_spanned(
351 recv,
352 "extern \"C-unwind\" functions cannot have a `self` parameter. \
353 R's .Call interface only accepts SEXP arguments. \
354 Use `#[miniextendr(env|r6|s3|s4|s7)]` on an impl block for methods.",
355 ));
356 }
357 syn::FnArg::Typed(pat_type) => {
358 if let syn::Pat::Rest(_) = pat_type.pat.as_ref() {
359 return Err(syn::Error::new_spanned(
360 pat_type,
361 "extern functions cannot use variadic (...) - .Call passes fixed arguments",
362 ));
363 }
364 let is_sexp = match pat_type.ty.as_ref() {
365 syn::Type::Path(type_path) => type_path
366 .path
367 .segments
368 .last()
369 .is_some_and(|seg| seg.ident == "SEXP"),
370 _ => false,
371 };
372 if !is_sexp && crate::type_inspect::is_lazy_dots_marker(&pat_type.ty) {
373 return Err(syn::Error::new_spanned(
374 &pat_type.ty,
375 "extern functions cannot take `LazyDots`: it is the generated R \
376 wrapper's frame (`environment()`), and `.Call()` reaches an extern \
377 function directly. Drop the `extern \"C-unwind\"` to let the macro \
378 generate the wrapper",
379 ));
380 }
381 if !is_sexp {
382 let is_dots_type = if let syn::Type::Reference(type_ref) = pat_type.ty.as_ref()
383 {
384 if let syn::Type::Path(inner) = type_ref.elem.as_ref() {
385 inner
386 .path
387 .segments
388 .last()
389 .is_some_and(|seg| seg.ident == "Dots")
390 } else {
391 false
392 }
393 } else if let syn::Type::Path(type_path) = pat_type.ty.as_ref() {
394 type_path
395 .path
396 .segments
397 .last()
398 .is_some_and(|seg| seg.ident == "Dots")
399 } else {
400 false
401 };
402 let msg = if is_dots_type {
403 "extern functions cannot use Dots; use `...` syntax in non-extern #[miniextendr] functions instead"
404 } else {
405 "extern function parameters must be SEXP - .Call passes all arguments as SEXP"
406 };
407 return Err(syn::Error::new_spanned(&pat_type.ty, msg));
408 }
409 }
410 }
411 }
412
413 Ok(())
414}
415
416pub(crate) fn build_dots_validation_stmt(
424 dots_param: &syn::Ident,
425 spec_tokens: &proc_macro2::TokenStream,
426) -> syn::Stmt {
427 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "dots_typed");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&dots_param, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "typed");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&spec_tokens, &mut _s);
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "unwrap_or_else");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "e");
::quote::__private::push_or(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "arg_error");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "param");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"...\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s,
"\"dots validation failed: {e}\"");
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
_s
});syn::parse_quote! {
428 let dots_typed = #dots_param.typed(#spec_tokens)
429 .unwrap_or_else(|e| ::miniextendr_api::arg_error!(
430 param = "...", "dots validation failed: {e}"
431 ));
432 }
433}
434
435#[proc_macro_attribute]
775pub fn miniextendr(
776 attr: proc_macro::TokenStream,
777 item: proc_macro::TokenStream,
778) -> proc_macro::TokenStream {
779 let _ = deprecation::take();
781 let expanded = proc_macro2::TokenStream::from(expand_miniextendr(attr, item));
782 let warnings = deprecation::take();
783 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&expanded, &mut _s);
::quote::ToTokens::to_tokens(&warnings, &mut _s);
_s
}quote::quote! { #expanded #warnings }.into()
784}
785
786fn expand_miniextendr(
789 attr: proc_macro::TokenStream,
790 item: proc_macro::TokenStream,
791) -> proc_macro::TokenStream {
792 if let Ok(parsed) = syn::parse::<syn::Item>(item.clone()) {
794 match cfg_gates::select(&attr.clone().into(), &parsed) {
795 Ok(Some(selected)) => return selected.into(),
796 Ok(None) => {}
797 Err(error) => return error.into_compile_error().into(),
798 }
799 }
800
801 if syn::parse::<syn::ItemFn>(item.clone()).is_ok() {
803 expand_fn(attr.into(), item.into())
804 } else if syn::parse::<syn::ItemImpl>(item.clone()).is_ok() {
805 miniextendr_impl::expand_impl(attr, item)
807 } else if syn::parse::<syn::ItemTrait>(item.clone()).is_ok() {
808 miniextendr_trait::expand_trait(attr, item)
810 } else {
811 struct_enum_dispatch::expand_struct_or_enum(attr, item)
813 }
814}
815
816fn expand_fn<T: From<proc_macro2::TokenStream>>(
820 attr: proc_macro2::TokenStream,
821 item: proc_macro2::TokenStream,
822) -> T {
823 let MiniextendrFnAttrs {
824 force_worker,
825 force_invisible,
826 check_interrupt,
827 coerce_all,
828 rng,
829 rng_seed,
830 unwrap_in_r,
831 serialize,
832 wrap,
833 serde_error,
834 preconditions,
835 call_attribution: call_attribution_attr,
836 call_arg,
837 return_pref,
838 return_pref_span,
839 s3_generic,
840 s3_class,
841 dots_spec,
842 dots_policy,
843 dots_span,
844 lifecycle,
845 strict,
846 internal,
847 noexport,
848 export,
849 doc,
850 c_symbol,
851 r_name: fn_r_name,
852 postfix: fn_postfix,
853 r_entry,
854 r_post_checks,
855 r_on_exit,
856 } = match syn::parse2(attr) {
857 Ok(attrs) => attrs,
858 Err(err) => return err.into_compile_error().into(),
859 };
860
861 let mut parsed = match syn::parse2::<MiniextendrFunctionParsed>(item) {
862 Ok(parsed) => parsed,
863 Err(err) => return err.into_compile_error().into(),
864 };
865
866 if let Some(asyncness) = &parsed.item().sig.asyncness {
868 return syn::Error::new_spanned(
869 asyncness,
870 "async functions are not supported by #[miniextendr]; \
871 R's C API is synchronous and incompatible with async executors",
872 )
873 .into_compile_error()
874 .into();
875 }
876
877 {
882 let params = &parsed.item().sig.generics.params;
883 let has_type_or_const = params
884 .iter()
885 .any(|p| #[allow(non_exhaustive_omitted_patterns)] match p {
syn::GenericParam::Type(_) | syn::GenericParam::Const(_) => true,
_ => false,
}matches!(p, syn::GenericParam::Type(_) | syn::GenericParam::Const(_)));
886
887 if has_type_or_const {
888 let err = syn::Error::new_spanned(
889 &parsed.item().sig.generics,
890 "#[miniextendr] functions cannot have generic type or const parameters. \
891 Generic functions are incompatible with `extern \"C-unwind\"` and `#[no_mangle]` \
892 required for R FFI. Consider using trait objects or monomorphization instead. \
893 Explicit lifetime parameters are allowed (lifetimes are erased at codegen).",
894 );
895 return err.into_compile_error().into();
896 }
897 }
898
899 parsed.add_inline_never_if_needed();
904
905 let uses_internal_c_wrapper = parsed.uses_internal_c_wrapper();
907 let c_ident = if let Some(ref sym) = c_symbol {
908 syn::Ident::new(sym, parsed.c_wrapper_ident().span())
909 } else {
910 parsed.c_wrapper_ident()
911 };
912 let r_wrapper_generator = parsed.r_wrapper_const_ident();
913
914 let rust_ident = parsed.ident();
916 let all_inputs = parsed.inputs();
917 let (visibility_marker, peeled_output) = {
921 let output = parsed.output();
922 if let syn::ReturnType::Type(_, ty) = output
923 && let Some(err) = crate::type_inspect::visibility_marker_error(ty, "return")
924 {
925 return err.into_compile_error().into();
926 }
927 crate::type_inspect::peel_return_visibility(output)
928 };
929 let (return_wrap, peeled_output) = match crate::return_wrap::resolve(&peeled_output, wrap) {
930 Ok(resolved) => resolved,
931 Err(error) => return error.into_compile_error().into(),
932 };
933 if return_wrap
934 .as_ref()
935 .is_some_and(|wrap| wrap.conversion.is_some())
936 {
937 return syn::Error::new_spanned(
938 parsed.output(),
939 "ConvertTo/ConvertFrom require an inherent S7 impl method",
940 )
941 .into_compile_error()
942 .into();
943 }
944 if return_wrap.is_some() && (serialize || unwrap_in_r) {
945 return syn::Error::new_spanned(
946 parsed.output(),
947 "explicit class wrapping cannot be combined with serialize or unwrap_in_r",
948 )
949 .into_compile_error()
950 .into();
951 }
952 if return_wrap.is_some() && parsed.abi().is_some() {
953 return syn::Error::new_spanned(parsed.output(), "explicit class wrapping requires a generated Rust-to-R wrapper, not an extern function").into_compile_error().into();
954 }
955 let converted_output = crate::type_inspect::serialize_return_type(&peeled_output, serialize);
956 let output = &converted_output;
957 let abi = parsed.abi();
958 if serialize && abi.is_some() {
959 return syn::Error::new_spanned(
960 parsed.output(),
961 "`serialize` requires a generated Rust-to-R conversion and cannot be used on an extern function",
962 )
963 .into_compile_error()
964 .into();
965 }
966 let attrs = parsed.attrs();
967 let vis = parsed.vis();
968 let generics = parsed.generics();
969 let has_dots = parsed.has_dots();
970 let dots_ident = parsed.dots_ident().cloned();
971 let formals = parsed.formals();
974
975 if let Some(user_abi) = abi
978 && let Err(e) = validate_extern_signature(user_abi, attrs, all_inputs, output)
979 {
980 return e.into_compile_error().into();
981 }
982
983 let mut call_marker: Option<(syn::Ident, r_wrapper_builder::CallAttribution)> = None;
989 for arg in all_inputs.iter() {
990 let syn::FnArg::Typed(pt) = arg else {
991 continue;
992 };
993 let Some(kind) = crate::type_inspect::call_marker(&pt.ty) else {
994 continue;
995 };
996 let syn::Pat::Ident(pat_ident) = pt.pat.as_ref() else {
997 continue;
998 };
999 let marker = kind
1000 .marker_name()
1001 .expect("a marker type selects an attribution that has a marker");
1002 if let Some((first, _)) = &call_marker {
1003 return syn::Error::new_spanned(
1004 pt,
1005 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a `#[miniextendr]` function takes at most one `Call` / `CallerCall` parameter (`{0}` already receives the condition call); the call slot is a single value",
first))
})format!(
1006 "a `#[miniextendr]` function takes at most one `Call` / `CallerCall` \
1007 parameter (`{first}` already receives the condition call); the call \
1008 slot is a single value"
1009 ),
1010 )
1011 .into_compile_error()
1012 .into();
1013 }
1014 if parsed.has_param_attrs(&crate::naming::ident_name(&pat_ident.ident)) {
1015 return syn::Error::new_spanned(
1016 pt,
1017 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("per-parameter options (`coerce`, `match_arg`, `choices`, `default`, `several_ok`, `formal`) do not apply to a `{0}` parameter: it is bound from the call slot, not from an R argument",
marker))
})format!(
1018 "per-parameter options (`coerce`, `match_arg`, `choices`, `default`, \
1019 `several_ok`, `formal`) do not apply to a `{marker}` parameter: it is \
1020 bound from the call slot, not from an R argument"
1021 ),
1022 )
1023 .into_compile_error()
1024 .into();
1025 }
1026 if kind == r_wrapper_builder::CallAttribution::Caller && !(noexport || internal) {
1027 return syn::Error::new_spanned(
1028 pt,
1029 "a `CallerCall` parameter attributes conditions to the wrapper's caller, which \
1030 is only meaningful for a package-internal entry point; add `noexport` or \
1031 `internal`.",
1032 )
1033 .into_compile_error()
1034 .into();
1035 }
1036 if kind == r_wrapper_builder::CallAttribution::Caller && call_arg {
1037 return syn::Error::new_spanned(
1038 pt,
1039 "a `CallerCall` parameter cannot be combined with `call_arg`: a `caller` wrapper \
1040 already takes `.call`, where NULL means the caller's call. Keep the \
1041 `CallerCall` parameter, or make it `Call` so that NULL means this function's \
1042 own call.",
1043 )
1044 .into_compile_error()
1045 .into();
1046 }
1047 if call_attribution_attr == Some(r_wrapper_builder::CallAttribution::NoCall) {
1048 return syn::Error::new_spanned(
1049 pt,
1050 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`call = none` passes no call, so a `{0}` parameter has nothing to receive; drop the parameter or the option",
marker))
})format!(
1051 "`call = none` passes no call, so a `{marker}` parameter has nothing to \
1052 receive; drop the parameter or the option"
1053 ),
1054 )
1055 .into_compile_error()
1056 .into();
1057 }
1058 if let Some(attr) = call_attribution_attr
1059 && attr != kind
1060 {
1061 return syn::Error::new_spanned(
1062 pt,
1063 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the `{3}` parameter selects `{0}` attribution but the attribute selects `{1}` (`call = {2}`); keep one of them (or make them agree)",
kind.name(), attr.name(), attr.name(), marker))
})format!(
1064 "the `{marker}` parameter selects `{}` attribution but the attribute \
1065 selects `{}` (`call = {}`); keep one of them (or make them agree)",
1066 kind.name(),
1067 attr.name(),
1068 attr.name(),
1069 ),
1070 )
1071 .into_compile_error()
1072 .into();
1073 }
1074 call_marker = Some((pat_ident.ident.clone(), kind));
1075 }
1076 let mut unevaluated_r_names: Vec<String> = Vec::new();
1087 for arg in all_inputs.iter() {
1088 let syn::FnArg::Typed(pt) = arg else {
1089 continue;
1090 };
1091 let Some(param) = crate::type_inspect::unevaluated_param(&pt.ty) else {
1092 if crate::type_inspect::mentions_unevaluated_marker(&pt.ty) {
1093 return syn::Error::new_spanned(
1094 &pt.ty,
1095 "`Quoted` / `Quosure` must be the parameter's whole type, or the type \
1096 argument of `Missing<..>`: the wrapper passes the argument unevaluated \
1097 only for those shapes",
1098 )
1099 .into_compile_error()
1100 .into();
1101 }
1102 continue;
1103 };
1104 let syn::Pat::Ident(pat_ident) = pt.pat.as_ref() else {
1105 continue;
1106 };
1107 let marker = param.kind.name();
1108 let rust_name = crate::naming::ident_name(&pat_ident.ident);
1109 if parsed
1111 .param_attrs(&rust_name)
1112 .is_some_and(|attrs| !attrs.leaves_argument_unforced(param.optional))
1113 {
1114 let hint = if param.optional {
1115 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Missing<{0}>` takes `default` alone, which only writes the formal and is never evaluated",
marker))
})format!(
1116 "`Missing<{marker}>` takes `default` alone, which only writes the \
1117 formal and is never evaluated"
1118 )
1119 } else {
1120 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Use `Missing<{0}>` for an optional argument",
marker))
})format!("Use `Missing<{marker}>` for an optional argument")
1121 };
1122 return syn::Error::new_spanned(
1123 pt,
1124 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("per-parameter options (`coerce`, `match_arg`, `choices`, `several_ok`, `default`, `no_na`, `inherits`, `not_inherits`, `preconditions`) do not apply to a `{0}` parameter: the wrapper passes the argument unevaluated, and each of them would force it (`formal`, which only names it, does apply). {1}",
marker, hint))
})format!(
1125 "per-parameter options (`coerce`, `match_arg`, `choices`, `several_ok`, \
1126 `default`, `no_na`, `inherits`, `not_inherits`, `preconditions`) do not \
1127 apply to a `{marker}` parameter: the wrapper passes the argument \
1128 unevaluated, and each of them would force it (`formal`, which only \
1129 names it, does apply). {hint}"
1130 ),
1131 )
1132 .into_compile_error()
1133 .into();
1134 }
1135 unevaluated_r_names.push(formals.of(&rust_name));
1138 }
1139 if let Err(err) =
1145 miniextendr_fn::check_nargs_params(all_inputs, |name| parsed.has_param_attrs(name))
1146 {
1147 return err.into_compile_error().into();
1148 }
1149 if let Err(err) =
1153 miniextendr_fn::check_lazy_dots_params(all_inputs, |name| parsed.has_param_attrs(name))
1154 {
1155 return err.into_compile_error().into();
1156 }
1157 if let Err(err) =
1160 miniextendr_fn::check_rng_guard_params(all_inputs, rng, |name| parsed.has_param_attrs(name))
1161 {
1162 return err.into_compile_error().into();
1163 }
1164 let has_rng_guard = all_inputs.iter().any(|arg| {
1165 #[allow(non_exhaustive_omitted_patterns)] match arg {
syn::FnArg::Typed(pt) if crate::type_inspect::is_rng_guard_param(&pt.ty)
=> true,
_ => false,
}matches!(arg, syn::FnArg::Typed(pt) if crate::type_inspect::is_rng_guard_param(&pt.ty))
1166 });
1167 let r_inputs: syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]> = all_inputs
1168 .iter()
1169 .filter(|arg| match arg {
1170 syn::FnArg::Typed(pt) => {
1171 crate::type_inspect::call_marker(&pt.ty).is_none()
1172 && !crate::type_inspect::is_rng_guard_param(&pt.ty)
1173 }
1174 syn::FnArg::Receiver(_) => true,
1175 })
1176 .cloned()
1177 .collect();
1178 let inputs = &r_inputs;
1179
1180 if let Some(generic) = &s3_generic
1184 && let Err(err) = miniextendr_fn::check_replacement_value_param(
1185 crate::naming::split_generic(generic).1,
1186 inputs,
1187 &formals,
1188 rust_ident.span(),
1189 )
1190 {
1191 return err.into_compile_error().into();
1192 }
1193
1194 let doc_lint_warnings = if doc.is_some() {
1197 proc_macro2::TokenStream::new()
1198 } else {
1199 crate::roxygen::doc_conflict_warnings(attrs, rust_ident.span())
1200 };
1201
1202 let rust_inputs: Vec<proc_macro2::TokenStream> = all_inputs
1207 .iter()
1208 .filter_map(|arg| {
1209 if let syn::FnArg::Typed(pt) = arg
1210 && let syn::Pat::Ident(p) = pt.pat.as_ref()
1211 {
1212 let ident = &p.ident;
1213 if crate::type_inspect::is_rng_guard_param(&pt.ty) {
1214 return Some(crate::type_inspect::rng_guard_arg());
1215 }
1216 return Some(match crate::type_inspect::call_marker(&pt.ty) {
1217 Some(r_wrapper_builder::CallAttribution::Caller) => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CallerCall");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__miniextendr_call");
_s
});
_s
}quote::quote! {
1218 ::miniextendr_api::CallerCall::from_sexp(__miniextendr_call)
1219 },
1220 Some(_) => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Call");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "from_sexp");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__miniextendr_call");
_s
});
_s
}quote::quote! {
1221 ::miniextendr_api::Call::from_sexp(__miniextendr_call)
1222 },
1223 None => {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&ident, &mut _s);
_s
}quote::quote! { #ident },
1224 });
1225 }
1226 None
1227 })
1228 .collect();
1229
1230 if dots_spec.is_some() && !has_dots {
1232 let err = syn::Error::new(
1233 dots_span.unwrap_or_else(proc_macro2::Span::call_site),
1234 "#[miniextendr(dots = typed_list!(...))] requires a `...` or `&Dots` parameter in the function signature",
1235 );
1236 return err.into_compile_error().into();
1237 }
1238 if dots_spec.is_some()
1239 && let Some(err) = miniextendr_fn::typed_list_on_lazy_dots(all_inputs, dots_span)
1240 {
1241 return err.into_compile_error().into();
1242 }
1243 if let Some(policy) = &dots_policy
1246 && let Err(err) = policy.check_signature(has_dots, has_dots)
1247 {
1248 return err.into_compile_error().into();
1249 }
1250
1251 let rust_result_ident =
1255 syn::Ident::new("__miniextendr_rust_result", proc_macro2::Span::mixed_site());
1256 if serde_error.is_some() && !return_type_analysis::output_is_result(output) {
1258 return syn::Error::new_spanned(
1259 output,
1260 "`#[miniextendr(serde_error(..))]` requires a `Result<T, E>` return type: it classes \
1261 the condition raised from the `Err` arm",
1262 )
1263 .into_compile_error()
1264 .into();
1265 }
1266 let err_parts = c_wrapper_builder::ErrPartsMode::from_spec(serde_error.as_ref());
1267
1268 let crate_config = match crate::crate_config::crate_config() {
1273 Ok(config) => config,
1274 Err(err) => {
1275 return syn::Error::new(proc_macro2::Span::call_site(), err.to_string())
1276 .into_compile_error()
1277 .into();
1278 }
1279 };
1280
1281 let is_s3_method = s3_generic.is_some() || s3_class.is_some();
1283 let effective_postfix = match &fn_postfix {
1290 Some(postfix) => Some(postfix.clone()),
1291 None if (noexport || internal) && fn_r_name.is_none() && !is_s3_method => {
1292 crate_config.noexport_postfix.clone()
1293 }
1294 None => None,
1295 };
1296 let r_wrapper_ident_str: String;
1297 let s3_method_comment: String;
1298 let mut s3_qualified_registration: Option<String> = None;
1300
1301 if is_s3_method {
1302 let generic = s3_generic
1305 .clone()
1306 .unwrap_or_else(|| crate::naming::ident_name(rust_ident));
1307 let (package, generic) = crate::naming::split_generic(&generic);
1308 let class = s3_class.as_ref().expect("s3_class validated at parse time");
1311 r_wrapper_ident_str = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}.{1}", generic, class))
})format!("{}.{}", generic, class);
1312 let import_comment =
1316 if package.is_none() && crate::vctrs_generics::is_vctrs_generic(generic) {
1317 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#\' @importFrom vctrs {0}\n",
generic))
})format!("#' @importFrom vctrs {}\n", generic)
1318 } else {
1319 String::new()
1320 };
1321 s3_method_comment = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}#\' @method {1} {2}\n",
import_comment, generic, class))
})format!("{}#' @method {} {}\n", import_comment, generic, class);
1322 s3_qualified_registration =
1323 package.map(|package| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#\' @exportS3Method {0}::{1} {2}\n",
package, generic, class))
})format!("#' @exportS3Method {package}::{generic} {class}\n"));
1324 } else if let Some(ref custom_name) = fn_r_name {
1325 r_wrapper_ident_str = custom_name.clone();
1326 s3_method_comment = String::new();
1327 } else if let Some(ref postfix) = effective_postfix {
1328 r_wrapper_ident_str = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}",
crate::naming::ident_name(rust_ident), postfix))
})format!("{}{postfix}", crate::naming::ident_name(rust_ident));
1331 s3_method_comment = String::new();
1332 } else if abi.is_some() {
1333 r_wrapper_ident_str = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unsafe_{0}",
crate::naming::ident_name(rust_ident)))
})format!("unsafe_{}", crate::naming::ident_name(rust_ident));
1334 s3_method_comment = String::new();
1335 } else {
1336 r_wrapper_ident_str = crate::naming::ident_name(rust_ident);
1337 s3_method_comment = String::new();
1338 };
1339
1340 let return_analysis = return_type_analysis::analyze_return_type(
1341 output,
1342 &rust_result_ident,
1343 &r_wrapper_ident_str,
1344 unwrap_in_r,
1345 strict,
1346 &err_parts,
1347 );
1348
1349 let returns_sexp = return_analysis.returns_sexp;
1350
1351 let is_invisible_return_type = match crate::type_inspect::resolve_visibility(
1354 visibility_marker,
1355 force_invisible,
1356 return_analysis.is_invisible,
1357 syn::spanned::Spanned::span(parsed.output()),
1358 ) {
1359 Ok(v) => v,
1360 Err(err) => return err.into_compile_error().into(),
1361 };
1362
1363 let has_sexp_inputs = all_inputs.iter().any(|arg| {
1368 if let syn::FnArg::Typed(pat_type) = arg {
1369 is_main_thread_bound_input(pat_type.ty.as_ref())
1370 } else {
1371 false
1372 }
1373 });
1374
1375 let has_main_thread_bound_return = match output {
1381 syn::ReturnType::Default => false,
1382 syn::ReturnType::Type(_, ty) => is_main_thread_bound_return(ty),
1383 };
1384
1385 let requires_main_thread = returns_sexp
1425 || has_sexp_inputs
1426 || has_rng_guard
1427 || !unevaluated_r_names.is_empty()
1428 || has_main_thread_bound_return
1429 || has_dots
1430 || check_interrupt;
1431 let use_main_thread = !force_worker || requires_main_thread;
1432
1433 let cfg_attrs = extract_cfg_attrs(parsed.attrs());
1435
1436 let source_loc_doc = source_location_doc(rust_ident.span());
1437
1438 let mut coerce_params_list: Vec<String> = Vec::new();
1442 let mut match_arg_several_ok_params_list: Vec<String> = Vec::new();
1443 let mut layered_choice_params_list: Vec<(String, rust_conversion_builder::ChoiceLeaf)> =
1444 Vec::new();
1445 let mut no_na_params_list: Vec<(String, Option<String>)> = Vec::new();
1446 for input in inputs.iter() {
1447 if let syn::FnArg::Typed(pt) = input
1448 && let syn::Pat::Ident(pat_ident) = pt.pat.as_ref()
1449 {
1450 let param_name = crate::naming::ident_name(&pat_ident.ident);
1451 if parsed.has_coerce_attr(¶m_name) {
1452 coerce_params_list.push(param_name.clone());
1453 }
1454 if let Some(attrs) = parsed.param_attrs(¶m_name)
1455 && attrs.checks.no_na
1456 {
1457 no_na_params_list.push((param_name.clone(), attrs.checks.no_na_message.clone()));
1458 }
1459 if let Some(leaf) = parsed
1460 .param_attrs(¶m_name)
1461 .and_then(miniextendr_fn::ParamAttrs::layered_leaf)
1462 {
1463 layered_choice_params_list.push((param_name, leaf));
1464 } else if parsed.has_match_arg_attr(¶m_name) && parsed.has_several_ok(¶m_name) {
1465 match_arg_several_ok_params_list.push(param_name);
1466 }
1467 }
1468 }
1469
1470 let fn_call_expr = crate::type_inspect::prepare_return_value(
1474 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&rust_ident, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut rust_inputs, i) = rust_inputs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let rust_inputs =
match rust_inputs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&rust_inputs, &mut _s);
}
}
_s
});
_s
}quote::quote! { #rust_ident(#(#rust_inputs),*) },
1475 visibility_marker,
1476 serialize,
1477 );
1478 let fn_call_expr = match &return_wrap {
1479 Some(wrap) => wrap.prepare_value(fn_call_expr),
1480 None => fn_call_expr,
1481 };
1482
1483 let return_pref_is_set = !#[allow(non_exhaustive_omitted_patterns)] match return_pref {
crate::miniextendr_fn::ReturnPref::Auto => true,
_ => false,
}matches!(return_pref, crate::miniextendr_fn::ReturnPref::Auto);
1486 let fn_return_handling = if unwrap_in_r && crate::return_type_analysis::output_is_result(output)
1487 {
1488 if return_pref_is_set {
1494 let span = return_pref_span.unwrap_or_else(proc_macro2::Span::call_site);
1495 return syn::Error::new(
1496 span,
1497 "`prefer = ...` cannot be combined with `unwrap_in_r` on a function returning \
1498 `Result<T, E>`: `unwrap_in_r` converts the whole `Result<T, E>` via a single \
1499 `IntoR` impl (a tagged list for R to decode), not the inner `T` alone, so \
1500 there is no plain `T` for `prefer=` to wrap. Remove `prefer=`.",
1501 )
1502 .into_compile_error()
1503 .into();
1504 }
1505 c_wrapper_builder::ReturnHandling::IntoR
1506 } else {
1507 let auto = c_wrapper_builder::detect_return_handling(output, return_wrap.as_ref());
1508 match apply_return_pref(auto, return_pref, return_pref_span) {
1513 Ok(handling) => handling,
1514 Err(err) => return err.into_compile_error().into(),
1515 }
1516 };
1517
1518 let rng_seed_formal = match &rng_seed {
1521 Some(seed) => {
1522 use c_wrapper_builder::ReturnHandling;
1523 let unit_return = #[allow(non_exhaustive_omitted_patterns)] match fn_return_handling {
ReturnHandling::Unit | ReturnHandling::ResultUnit |
ReturnHandling::OptionUnit => true,
_ => false,
}matches!(
1524 fn_return_handling,
1525 ReturnHandling::Unit | ReturnHandling::ResultUnit | ReturnHandling::OptionUnit
1526 );
1527 match miniextendr_fn::check_rng_seed(
1528 seed,
1529 all_inputs,
1530 inputs,
1531 &formals,
1532 &unevaluated_r_names,
1533 unit_return,
1534 ) {
1535 Ok(formal) => Some(formal),
1536 Err(err) => return err.into_compile_error().into(),
1537 }
1538 }
1539 None => None,
1540 };
1541
1542 let thread_strategy = if use_main_thread {
1543 c_wrapper_builder::ThreadStrategy::MainThread
1544 } else {
1545 c_wrapper_builder::ThreadStrategy::WorkerThread
1546 };
1547
1548 let mut c_wrapper_builder =
1550 c_wrapper_builder::CWrapperContext::builder(rust_ident.clone(), c_ident.clone())
1551 .r_name(r_wrapper_ident_str.clone())
1552 .r_wrapper_const(r_wrapper_generator.clone())
1553 .inputs(inputs.iter().cloned().collect())
1554 .output(output.clone())
1555 .call_expr(fn_call_expr)
1556 .thread_strategy(thread_strategy)
1557 .return_handling(fn_return_handling)
1558 .err_parts(err_parts)
1559 .cfg_attrs(cfg_attrs.clone())
1560 .vis(vis.clone())
1561 .generics(generics.clone())
1562 .formals(formals.clone())
1563 .preserve_param_names();
1564
1565 if uses_internal_c_wrapper {
1566 } else {
1568 c_wrapper_builder = c_wrapper_builder.skip_wrapper();
1570 }
1571
1572 if coerce_all {
1573 c_wrapper_builder = c_wrapper_builder.coerce_all();
1574 }
1575 for param in &coerce_params_list {
1576 c_wrapper_builder = c_wrapper_builder.with_coerce_param(param.clone());
1577 }
1578 for param in match_arg_several_ok_params_list {
1579 c_wrapper_builder = c_wrapper_builder.match_arg_several_ok(param);
1580 }
1581 for (param, leaf) in layered_choice_params_list {
1582 c_wrapper_builder = c_wrapper_builder.layered_choice(param, leaf);
1583 }
1584 for (param, message) in no_na_params_list {
1585 c_wrapper_builder = c_wrapper_builder.no_na(param, message);
1586 }
1587 for (param, markers) in parsed.param_markers() {
1588 c_wrapper_builder = c_wrapper_builder.param_markers(param.clone(), markers.clone());
1589 }
1590 if check_interrupt {
1591 c_wrapper_builder = c_wrapper_builder.check_interrupt();
1592 }
1593 if rng {
1594 c_wrapper_builder = c_wrapper_builder.rng();
1595 }
1596 if strict {
1597 c_wrapper_builder = c_wrapper_builder.strict();
1598 }
1599
1600 let c_wrapper = c_wrapper_builder.build().generate();
1601
1602 let mut arg_builder = RArgumentBuilder::new(inputs).with_formals(formals.clone());
1605 let mut merged_defaults = formals.rekey(parsed.param_defaults());
1609 let mut match_arg_placeholders: Vec<(String, String, String, String)> = Vec::new();
1619 for match_arg_param in parsed.match_arg_params() {
1620 let r_name = formals.of(match_arg_param);
1621 let preferred = match merged_defaults.get(&r_name) {
1622 Some(raw) => crate::match_arg_keys::extract_match_arg_default(raw),
1623 None => String::new(),
1624 };
1625 let key = crate::match_arg_keys::param_key(match_arg_param);
1628 let placeholder = crate::match_arg_keys::choices_placeholder(&c_ident.to_string(), &key);
1629 let formal = match parsed.param_attrs(match_arg_param) {
1634 Some(attrs) => attrs.choice_formal(&placeholder),
1635 None => Some(placeholder.clone()),
1636 };
1637 if let Some(formal) = formal {
1638 merged_defaults.insert(r_name.clone(), formal);
1639 }
1640 let aliases_placeholder =
1641 crate::match_arg_keys::aliases_placeholder(&c_ident.to_string(), &key);
1642 match_arg_placeholders.push((
1643 placeholder,
1644 aliases_placeholder,
1645 match_arg_param.clone(),
1646 preferred,
1647 ));
1648 }
1649 for (param_name, choices) in parsed.choices_params() {
1653 let r_name = formals.of(param_name);
1654 let quoted: Vec<String> = choices.iter().map(|c| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\"{0}\"", c))
})format!("\"{}\"", c)).collect();
1655 let choices_expr = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("c({0})", quoted.join(", ")))
})format!("c({})", quoted.join(", "));
1656 let formal = match parsed.param_attrs(param_name) {
1657 Some(attrs) => attrs.choice_formal(&choices_expr),
1658 None => Some(choices_expr),
1659 };
1660 if let Some(formal) = formal {
1661 merged_defaults.entry(r_name).or_insert(formal);
1662 }
1663 }
1664 arg_builder = arg_builder
1665 .with_defaults(merged_defaults)
1666 .with_absent_formals(parsed.absent_formals(&c_ident.to_string()));
1667
1668 let r_formals = arg_builder.build_formals();
1669 let mut r_call_args_strs = arg_builder.build_call_args_vec();
1670
1671 let call_attribution = r_wrapper_builder::CallAttribution::resolve(
1694 call_marker.as_ref().map(|(_, kind)| *kind),
1695 call_attribution_attr,
1696 crate_config.call_attribution.filter(|_| !call_arg),
1697 noexport || internal,
1698 )
1699 .with_call_arg(call_arg);
1700 let call_attribution = if is_s3_method {
1701 call_attribution.for_s3_method(call_marker.is_some())
1702 } else {
1703 call_attribution
1704 };
1705 if uses_internal_c_wrapper {
1706 r_call_args_strs.insert(0, call_attribution.dot_call_arg().to_string());
1707 } else if #[allow(non_exhaustive_omitted_patterns)] match call_attribution_attr {
Some(r_wrapper_builder::CallAttribution::Caller |
r_wrapper_builder::CallAttribution::NoCall) => true,
_ => false,
}matches!(
1708 call_attribution_attr,
1709 Some(
1710 r_wrapper_builder::CallAttribution::Caller | r_wrapper_builder::CallAttribution::NoCall
1711 )
1712 ) || call_arg
1713 {
1714 let option = if call_arg {
1717 "`call_arg`"
1718 } else if call_attribution_attr == Some(r_wrapper_builder::CallAttribution::NoCall) {
1719 "`call = none`"
1720 } else {
1721 "`call = caller`"
1722 };
1723 return syn::Error::new_spanned(
1724 &parsed.item().sig.ident,
1725 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} needs the generated call slot; an `extern \"C-unwind\"` function has no `.call` argument to attribute",
option))
})format!(
1726 "{option} needs the generated call slot; an `extern \"C-unwind\"` function \
1727 has no `.call` argument to attribute"
1728 ),
1729 )
1730 .into_compile_error()
1731 .into();
1732 }
1733
1734 let c_ident_str = c_ident.to_string();
1736 let call_args_joined = r_call_args_strs.join(", ");
1737 let call_expr = if r_call_args_strs.is_empty() {
1738 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".Call({0})", c_ident_str))
})format!(".Call({})", c_ident_str)
1739 } else {
1740 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(".Call({0}, {1})", c_ident_str,
call_args_joined))
})format!(".Call({}, {})", c_ident_str, call_args_joined)
1741 };
1742 let r_wrapper_return_str = {
1743 let final_return = return_wrap
1745 .as_ref()
1746 .map_or_else(|| ".val".to_owned(), |wrap| wrap.r_expression(".val", None));
1747 let final_return = if is_invisible_return_type {
1748 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invisible({0})", final_return))
})format!("invisible({final_return})")
1749 } else {
1750 final_return
1751 };
1752 let final_return = if rng_seed_formal.is_some() {
1755 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}\n {1}",
r_wrapper_builder::RngSeedContract::ATTRIBUTE, final_return))
})format!(
1756 "{}\n {final_return}",
1757 r_wrapper_builder::RngSeedContract::ATTRIBUTE
1758 )
1759 } else {
1760 final_return
1761 };
1762 crate::method_return_builder::standalone_body_with_call_default(
1765 &call_expr,
1766 &final_return,
1767 " ",
1768 call_attribution.raise_default(),
1769 )
1770 };
1771 let call_formal = call_attribution.formal().filter(|_| !is_s3_method);
1781 let formals_joined = r_wrapper_builder::with_call_formal(&r_formals, call_formal);
1784 let mut roxygen_tags = if let Some(ref doc_text) = doc {
1785 doc_text.lines().map(|l| l.to_string()).collect()
1787 } else {
1788 crate::roxygen::roxygen_tags_from_attrs(
1791 attrs,
1792 crate::roxygen::RdPage::suppressed_if(noexport),
1793 )
1794 };
1795
1796 let lifecycle_spec = lifecycle.or_else(|| {
1798 attrs
1799 .iter()
1800 .find_map(crate::lifecycle::parse_rust_deprecated)
1801 });
1802
1803 if let Some(ref spec) = lifecycle_spec {
1805 crate::lifecycle::inject_lifecycle_badge(&mut roxygen_tags, spec);
1806 }
1807
1808 let renders_no_page = noexport || crate::roxygen::has_roxygen_tag(&roxygen_tags, "noRd");
1817 let call_param_doc = call_formal
1818 .and(call_attribution.param_doc())
1819 .filter(|_| !renders_no_page);
1820 let match_arg_param_doc_placeholders = crate::roxygen::push_fn_param_tags(
1821 &mut roxygen_tags,
1822 inputs,
1823 &parsed,
1824 &c_ident_str,
1825 call_param_doc,
1826 );
1827
1828 let has_no_rd_tag = crate::roxygen::has_roxygen_tag(&roxygen_tags, "noRd");
1836 if !roxygen_tags.is_empty()
1837 && !has_no_rd_tag
1838 && !noexport
1839 && !crate::roxygen::has_roxygen_tag(&roxygen_tags, "title")
1840 {
1841 roxygen_tags.insert(0, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("@title {0}", r_wrapper_ident_str))
})format!("@title {}", r_wrapper_ident_str));
1842 }
1843
1844 let roxygen_tags_str = crate::roxygen::format_roxygen_tags(&roxygen_tags);
1845 let has_export_tag = crate::roxygen::has_export_tag(&roxygen_tags);
1846 let has_internal_tag = crate::roxygen::has_roxygen_tag(&roxygen_tags, "keywords internal");
1847 let source_comment = crate::roxygen::source_tag_with(
1850 crate_config.source_tags,
1851 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Generated by miniextendr from Rust fn `{0}`",
rust_ident))
})format!("Generated by miniextendr from Rust fn `{rust_ident}`"),
1852 )
1853 .map(|line| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}\n", line))
})format!("{line}\n"))
1854 .unwrap_or_default();
1855 let internal_comment = if internal && !has_internal_tag {
1857 "#' @keywords internal\n"
1858 } else {
1859 ""
1860 };
1861 let export_comment = if (#[allow(non_exhaustive_omitted_patterns)] match vis {
syn::Visibility::Public(_) => true,
_ => false,
}matches!(vis, syn::Visibility::Public(_)) || export)
1865 && !has_export_tag
1866 && !has_no_rd_tag
1867 && !has_internal_tag
1868 && !internal
1869 && !noexport
1870 {
1871 s3_qualified_registration.unwrap_or_else(|| "#' @export\n".to_string())
1876 } else {
1877 String::new()
1878 };
1879 let no_rd_comment = if noexport && !has_no_rd_tag {
1885 "#' @noRd\n"
1886 } else {
1887 ""
1888 };
1889 let match_arg_param_info: Vec<(String, String, &syn::Type)> = inputs
1892 .iter()
1893 .filter_map(|arg| {
1894 if let syn::FnArg::Typed(pt) = arg
1895 && let syn::Pat::Ident(pat_ident) = pt.pat.as_ref()
1896 {
1897 let rust_name = crate::naming::ident_name(&pat_ident.ident);
1898 if parsed.has_match_arg_attr(&rust_name) {
1899 let r_name = formals.of(&rust_name);
1900 return Some((r_name, rust_name, pt.ty.as_ref()));
1901 }
1902 }
1903 None
1904 })
1905 .collect();
1906
1907 let match_arg_prelude = if match_arg_param_info.is_empty() {
1908 String::new()
1909 } else {
1910 let mut lines = Vec::new();
1911 for (r_param, rust_name, _) in &match_arg_param_info {
1912 let key = crate::match_arg_keys::param_key(rust_name);
1922 let placeholder =
1923 crate::match_arg_keys::choices_placeholder(&c_ident.to_string(), &key);
1924 let aliases = crate::match_arg_keys::aliases_placeholder(&c_ident.to_string(), &key);
1925 if let Some(attrs) = parsed.param_attrs(rust_name) {
1926 lines.push(call_attribution.match_arg_statement(
1927 r_param,
1928 &placeholder,
1929 Some(&aliases),
1930 attrs,
1931 ));
1932 }
1933 }
1934 lines.join("\n ")
1935 };
1936
1937 let choices_prelude = {
1940 let mut lines = Vec::new();
1941 for arg in inputs.iter() {
1942 if let syn::FnArg::Typed(pt) = arg
1943 && let syn::Pat::Ident(pat_ident) = pt.pat.as_ref()
1944 {
1945 let rust_name = crate::naming::ident_name(&pat_ident.ident);
1946 if let Some(attrs) = parsed.param_attrs(&rust_name)
1947 && let Some(choices) = attrs.choices.as_ref()
1948 {
1949 let r_name = formals.of(&rust_name);
1950 let quoted: Vec<String> =
1951 choices.iter().map(|c| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\"{0}\"", c))
})format!("\"{}\"", c)).collect();
1952 let choices_expr = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("c({0})", quoted.join(", ")))
})format!("c({})", quoted.join(", "));
1953 lines.push(call_attribution.match_arg_statement(
1954 &r_name,
1955 &choices_expr,
1956 None,
1957 attrs,
1958 ));
1959 }
1960 }
1961 }
1962 if lines.is_empty() {
1963 String::new()
1964 } else {
1965 lines.join("\n ")
1966 }
1967 };
1968
1969 let lifecycle_prelude = lifecycle_spec
1971 .as_ref()
1972 .and_then(|spec| spec.r_prelude(&r_wrapper_ident_str));
1973
1974 let mut skip_params = parsed.precondition_skip_params();
1978 skip_params.extend(unevaluated_r_names.iter().cloned());
1979 let precondition_prelude = {
1993 let mut unchecked = r_preconditions::unchecked_params(
1996 inputs,
1997 &formals,
1998 |name| parsed.param_attrs(name).and_then(|a| a.preconditions),
1999 preconditions,
2000 None,
2001 crate_config.preconditions,
2002 );
2003 unchecked.extend(rng_seed_formal.iter().cloned());
2004 let precondition_opts = r_preconditions::PreconditionOptions {
2008 coerce_all,
2009 coerce_params: coerce_params_list.iter().map(|p| formals.of(p)).collect(),
2010 explicit: parsed.explicit_checks(),
2011 unchecked,
2012 formals: formals.clone(),
2013 };
2014 let precondition_output =
2015 r_preconditions::build_precondition_checks(inputs, &skip_params, &precondition_opts);
2016 precondition_output
2020 .guards(call_attribution.r_check_call())
2021 .join("\n ")
2022 };
2023
2024 let dots_check = dots_policy
2028 .as_ref()
2029 .and_then(|policy| policy.r_check(&formals_joined, call_attribution.r_check_call()));
2030
2031 let on_exit_str = r_on_exit.as_ref().map(|oe| oe.to_r_code());
2040 let rng_seed_prelude = rng_seed_formal
2041 .as_deref()
2042 .map(|formal| r_wrapper_builder::RngSeedContract { formal }.prelude(" "));
2043 let attribution_prelude = call_attribution.prelude(call_formal.is_some());
2044 let combined_prelude = {
2045 let mut parts = Vec::new();
2046 if !attribution_prelude.is_empty() {
2047 parts.push(attribution_prelude.as_str());
2048 }
2049 if let Some(ref entry) = r_entry {
2050 parts.push(entry.as_str());
2051 }
2052 if let Some(ref s) = on_exit_str {
2053 parts.push(s.as_str());
2054 }
2055 if let Some(ref lc) = lifecycle_prelude {
2056 parts.push(lc.as_str());
2057 }
2058 if let Some(ref check) = dots_check {
2059 parts.push(check.as_str());
2060 }
2061 if !precondition_prelude.is_empty() {
2062 parts.push(&precondition_prelude);
2063 }
2064 if !match_arg_prelude.is_empty() {
2065 parts.push(&match_arg_prelude);
2066 }
2067 if !choices_prelude.is_empty() {
2068 parts.push(&choices_prelude);
2069 }
2070 if let Some(ref post) = r_post_checks {
2071 parts.push(post.as_str());
2072 }
2073 if let Some(ref seed) = rng_seed_prelude {
2074 parts.push(seed.as_str());
2075 }
2076 if parts.is_empty() {
2077 None
2078 } else {
2079 Some(parts.join("\n "))
2080 }
2081 };
2082
2083 let r_wrapper_string = if let Some(prelude) = combined_prelude {
2084 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}{3}{4}{5}{6} <- function({7}) {{\n {8}\n {9}\n}}",
roxygen_tags_str, source_comment, s3_method_comment,
internal_comment, no_rd_comment, export_comment,
crate::naming::r_def_name(&r_wrapper_ident_str),
formals_joined, prelude, r_wrapper_return_str))
})format!(
2085 "{}{}{}{}{}{}{} <- function({}) {{\n {}\n {}\n}}",
2086 roxygen_tags_str,
2087 source_comment,
2088 s3_method_comment,
2089 internal_comment,
2090 no_rd_comment,
2091 export_comment,
2092 crate::naming::r_def_name(&r_wrapper_ident_str),
2093 formals_joined,
2094 prelude,
2095 r_wrapper_return_str
2096 )
2097 } else {
2098 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}{2}{3}{4}{5}{6} <- function({7}) {{\n {8}\n}}",
roxygen_tags_str, source_comment, s3_method_comment,
internal_comment, no_rd_comment, export_comment,
crate::naming::r_def_name(&r_wrapper_ident_str),
formals_joined, r_wrapper_return_str))
})format!(
2099 "{}{}{}{}{}{}{} <- function({}) {{\n {}\n}}",
2100 roxygen_tags_str,
2101 source_comment,
2102 s3_method_comment,
2103 internal_comment,
2104 no_rd_comment,
2105 export_comment,
2106 crate::naming::r_def_name(&r_wrapper_ident_str),
2107 formals_joined,
2108 r_wrapper_return_str
2109 )
2110 };
2111 let r_wrapper_str = r_wrapper_raw_literal(
2113 &r_wrapper_string,
2114 &r_shadowing::formal_names([(inputs, formals.clone())]),
2115 );
2116
2117 let r_wrapper_doc = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("R wrapper code for [`{0}`], calls [`{1}`].",
rust_ident, c_ident))
})format!(
2121 "R wrapper code for [`{}`], calls [`{}`].",
2122 rust_ident, c_ident
2123 );
2124 let source_start = rust_ident.span().start();
2125 let source_line_lit = syn::LitInt::new(&source_start.line.to_string(), rust_ident.span());
2126 let source_col_lit =
2127 syn::LitInt::new(&(source_start.column + 1).to_string(), rust_ident.span());
2128
2129 let mut original_item = parsed.item_without_roxygen();
2132 original_item
2134 .attrs
2135 .retain(|attr| !attr.path().is_ident("miniextendr"));
2136
2137 if let (Some(spec_tokens), Some(dots_param)) = (&dots_spec, &dots_ident) {
2140 let validation_stmt = build_dots_validation_stmt(dots_param, spec_tokens);
2141 original_item.block.stmts.insert(0, validation_stmt);
2142 }
2143
2144 let original_item = original_item;
2145
2146 let choices_ty_for = |rust_param: &str| -> Option<&syn::Type> {
2151 let (_, _, param_ty) = match_arg_param_info
2152 .iter()
2153 .find(|(_, rn, _)| rn == rust_param)?;
2154 Some(match_arg_choices_ty(
2155 param_ty,
2156 parsed.has_several_ok(rust_param),
2157 ))
2158 };
2159
2160 let match_arg_choices_entries: Vec<proc_macro2::TokenStream> = match_arg_placeholders
2161 .iter()
2162 .filter_map(
2163 |(placeholder, aliases_placeholder, rust_param, preferred_default)| {
2164 let choices_ty = choices_ty_for(rust_param)?;
2165 let entry_ident = syn::Ident::new(
2166 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("match_arg_choices_entry_{0}",
crate::match_arg_keys::placeholder_ident_suffix(placeholder)))
})format!(
2167 "match_arg_choices_entry_{}",
2168 crate::match_arg_keys::placeholder_ident_suffix(placeholder)
2169 ),
2170 proc_macro2::Span::call_site(),
2171 );
2172 Some(crate::match_arg_keys::choices_entry_tokens(
2173 &cfg_attrs,
2174 &entry_ident,
2175 placeholder,
2176 aliases_placeholder,
2177 choices_ty,
2178 preferred_default,
2179 ))
2180 },
2181 )
2182 .collect();
2183
2184 let match_arg_param_doc_entries: Vec<proc_macro2::TokenStream> =
2186 match_arg_param_doc_placeholders
2187 .iter()
2188 .filter_map(|(doc_placeholder, rust_param)| {
2189 let choices_ty = choices_ty_for(rust_param)?;
2190 let attrs = parsed.param_attrs(rust_param)?;
2191 let entry_ident = syn::Ident::new(
2192 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("match_arg_param_doc_entry_{0}",
crate::match_arg_keys::placeholder_ident_suffix(doc_placeholder)))
})format!(
2193 "match_arg_param_doc_entry_{}",
2194 crate::match_arg_keys::placeholder_ident_suffix(doc_placeholder)
2195 ),
2196 proc_macro2::Span::call_site(),
2197 );
2198 Some(crate::match_arg_keys::param_doc_entry_tokens(
2199 &cfg_attrs,
2200 &entry_ident,
2201 doc_placeholder,
2202 attrs.several_ok,
2203 &attrs.choice_doc_suffix(),
2204 choices_ty,
2205 ))
2206 })
2207 .collect();
2208
2209 let fn_r_wrapper_doc = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("See [`{0}`] for C wrapper, [`{1}`] for R wrapper.",
c_ident, r_wrapper_generator))
})format!(
2211 "See [`{}`] for C wrapper, [`{}`] for R wrapper.",
2212 c_ident, r_wrapper_generator
2213 );
2214
2215 let expanded: T = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&fn_r_wrapper_doc, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&original_item, &mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut cfg_attrs, i) = cfg_attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let cfg_attrs =
match cfg_attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&cfg_attrs, &mut _s);
}
}
::quote::ToTokens::to_tokens(&c_wrapper, &mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut cfg_attrs, i) = cfg_attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let cfg_attrs =
match cfg_attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&cfg_attrs, &mut _s);
}
}
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&r_wrapper_doc, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Wraps Rust function `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "stringify");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&rust_ident, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&source_loc_doc, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Generated from source file `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "cfg_attr");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "not");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "target_arch");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm32\"");
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"distributed_slice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "MX_R_WRAPPERS");
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "crate");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
_s
});
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"non_upper_case_globals");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "non_snake_case");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "static");
::quote::ToTokens::to_tokens(&r_wrapper_generator, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RWrapperEntry");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RWrapperEntry");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "priority");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RWrapperPriority");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Function");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "source_file");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "source_line");
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&source_line_lit, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "content");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"# Generated from Rust fn `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "stringify");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&rust_ident, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"` (\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\":\"");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&source_line_lit, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\":\"");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&source_col_lit, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\")\"");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&r_wrapper_str, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut match_arg_choices_entries, i) =
match_arg_choices_entries.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let match_arg_choices_entries =
match match_arg_choices_entries.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&match_arg_choices_entries, &mut _s);
}
}
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut match_arg_param_doc_entries, i) =
match_arg_param_doc_entries.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let match_arg_param_doc_entries =
match match_arg_param_doc_entries.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&match_arg_param_doc_entries,
&mut _s);
}
}
::quote::ToTokens::to_tokens(&doc_lint_warnings, &mut _s);
_s
}quote::quote! {
2216 #[doc = #fn_r_wrapper_doc]
2218 #original_item
2219
2220 #(#cfg_attrs)*
2222 #c_wrapper
2223
2224 #(#cfg_attrs)*
2226 #[doc = #r_wrapper_doc]
2227 #[doc = ::core::concat!("Wraps Rust function `", ::core::stringify!(#rust_ident), "`.")]
2228 #[doc = #source_loc_doc]
2229 #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
2230 #[cfg_attr(not(target_arch = "wasm32"), ::miniextendr_api::linkme::distributed_slice(::miniextendr_api::registry::MX_R_WRAPPERS), linkme(crate = ::miniextendr_api::linkme))]
2231 #[allow(non_upper_case_globals)]
2232 #[allow(non_snake_case)]
2233 static #r_wrapper_generator: ::miniextendr_api::registry::RWrapperEntry =
2234 ::miniextendr_api::registry::RWrapperEntry {
2235 priority: ::miniextendr_api::registry::RWrapperPriority::Function,
2236 source_file: ::core::file!(),
2237 source_line: #source_line_lit,
2238 content: ::core::concat!(
2239 "# Generated from Rust fn `",
2240 ::core::stringify!(#rust_ident),
2241 "` (",
2242 ::core::file!(),
2243 ":",
2244 #source_line_lit,
2245 ":",
2246 #source_col_lit,
2247 ")",
2248 #r_wrapper_str
2249 ),
2250 };
2251
2252 #(#match_arg_choices_entries)*
2254
2255 #(#match_arg_param_doc_entries)*
2257
2258 #doc_lint_warnings
2260 }
2261 .into();
2262
2263 expanded
2264}
2265
2266fn apply_return_pref(
2276 auto: c_wrapper_builder::ReturnHandling,
2277 pref: crate::miniextendr_fn::ReturnPref,
2278 pref_span: Option<proc_macro2::Span>,
2279) -> syn::Result<c_wrapper_builder::ReturnHandling> {
2280 use crate::miniextendr_fn::ReturnPref;
2281 use c_wrapper_builder::ReturnHandling;
2282
2283 let wrapped = match pref {
2284 ReturnPref::Auto => return Ok(auto),
2285 ReturnPref::List => match auto {
2286 ReturnHandling::IntoR => Some(ReturnHandling::AsListOf),
2287 _ => None,
2288 },
2289 ReturnPref::ExternalPtr => match auto {
2290 ReturnHandling::IntoR => Some(ReturnHandling::AsExternalPtrOf),
2291 _ => None,
2292 },
2293 ReturnPref::Native => match auto {
2294 ReturnHandling::IntoR => Some(ReturnHandling::AsNativeOf),
2295 _ => None,
2296 },
2297 };
2298
2299 wrapped.ok_or_else(|| {
2300 let (pref_name, wrapper_name) = return_pref_names(pref);
2301 let span = pref_span.unwrap_or_else(proc_macro2::Span::call_site);
2302 syn::Error::new(
2303 span,
2304 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`prefer = \"{1}\"` cannot be honored on this return type. `prefer=` only applies to a function returning a plain `T: IntoR` value, which it wraps in `{2}` before conversion. This function\'s return type falls into a different codegen category ({0}) with its own fixed SEXP-shape rule, so there is no plain `T` for `prefer=` to wrap. Remove `prefer=`, or change the return type to a plain `T`.",
return_handling_category_description(&auto), pref_name,
wrapper_name))
})format!(
2305 "`prefer = \"{pref_name}\"` cannot be honored on this return type. \
2306 `prefer=` only applies to a function returning a plain `T: IntoR` value, \
2307 which it wraps in `{wrapper_name}` before conversion. This function's return \
2308 type falls into a different codegen category ({}) with its own fixed \
2309 SEXP-shape rule, so there is no plain `T` for `prefer=` to wrap. Remove \
2310 `prefer=`, or change the return type to a plain `T`.",
2311 return_handling_category_description(&auto),
2312 ),
2313 )
2314 })
2315}
2316
2317fn return_pref_names(pref: crate::miniextendr_fn::ReturnPref) -> (&'static str, &'static str) {
2320 use crate::miniextendr_fn::ReturnPref;
2321 match pref {
2322 ReturnPref::Auto => ("auto", ""),
2323 ReturnPref::List => ("list", "AsList"),
2324 ReturnPref::ExternalPtr => ("externalptr", "AsExternalPtr"),
2325 ReturnPref::Native => ("native", "AsRNative"),
2326 }
2327}
2328
2329fn return_handling_category_description(rh: &c_wrapper_builder::ReturnHandling) -> &'static str {
2336 use c_wrapper_builder::ReturnHandling;
2337 match rh {
2338 ReturnHandling::Unit => "the unit return type `()`",
2339 ReturnHandling::RawSexp => "a raw `SEXP` return type",
2340 ReturnHandling::ExternalPtr => {
2341 "a `Self`-returning constructor, already converted via `ExternalPtr::new`"
2342 }
2343 ReturnHandling::OptionUnit => "`Option<()>`",
2344 ReturnHandling::OptionSexp => "`Option<SEXP>`",
2345 ReturnHandling::OptionIntoR | ReturnHandling::OptionClassPayload => "`Option<T>`",
2346 ReturnHandling::ResultUnit => "`Result<(), E>`",
2347 ReturnHandling::ResultSexp => "`Result<SEXP, E>`",
2348 ReturnHandling::ResultIntoR => "`Result<T, E>`",
2349 ReturnHandling::ResultNullOnErr => "`Result<T, ()>`",
2350 _ => "this return type",
2351 }
2352}
2353
2354#[proc_macro_attribute]
2424pub fn r_ffi_checked(
2425 _attr: proc_macro::TokenStream,
2426 item: proc_macro::TokenStream,
2427) -> proc_macro::TokenStream {
2428 let foreign_mod = match ::syn::parse::<syn::ItemForeignMod>(item) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(item as syn::ItemForeignMod);
2429
2430 let foreign_mod_attrs = &foreign_mod.attrs;
2431 let abi = &foreign_mod.abi;
2432 let mut unchecked_items = Vec::new();
2433 let mut checked_wrappers = Vec::new();
2434
2435 for item in &foreign_mod.items {
2436 match item {
2437 syn::ForeignItem::Fn(fn_item) => {
2438 let is_variadic = fn_item.sig.variadic.is_some();
2439
2440 let has_link_name = fn_item
2442 .attrs
2443 .iter()
2444 .any(|attr| attr.path().is_ident("link_name"));
2445
2446 if is_variadic || has_link_name {
2447 unchecked_items.push(item.clone());
2449 } else {
2450 let vis = &fn_item.vis;
2452 let fn_name = &fn_item.sig.ident;
2453 let fn_name_str = fn_name.to_string();
2454 let unchecked_name = match ::quote::__private::IdentFragmentAdapter(&fn_name) {
arg =>
::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}_unchecked", arg))
}), ::quote::__private::Option::None.or(arg.span())),
}quote::format_ident!("{}_unchecked", fn_name);
2455 let unchecked_name_str = unchecked_name.to_string();
2456 let inputs = &fn_item.sig.inputs;
2457 let output = &fn_item.sig.output;
2458 let attrs: Vec<_> = fn_item
2460 .attrs
2461 .iter()
2462 .filter(|attr| !attr.path().is_ident("link_name"))
2463 .collect();
2464 let checked_doc = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Checked wrapper for `{0}`. Calls `{1}` and routes through `with_r_thread`.",
fn_name_str, unchecked_name_str))
})format!(
2465 "Checked wrapper for `{}`. Calls `{}` and routes through `with_r_thread`.",
2466 fn_name_str, unchecked_name_str
2467 );
2468 let checked_doc_lit = syn::LitStr::new(&checked_doc, fn_name.span());
2469 let source_loc_doc = crate::source_location_doc(fn_name.span());
2470 let source_loc_doc_lit = syn::LitStr::new(&source_loc_doc, fn_name.span());
2471
2472 let link_name = syn::LitStr::new(&fn_name_str, fn_name.span());
2475 let unchecked_fn: syn::ForeignItem = ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut attrs, i) = attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let attrs =
match attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&attrs, &mut _s);
}
}
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Unchecked FFI binding for `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "stringify");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&fn_name, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&source_loc_doc_lit, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Generated from source file `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "link_name");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&link_name, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&vis, &mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&unchecked_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&inputs, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&output, &mut _s);
::quote::__private::push_semi(&mut _s);
_s
})syn::parse_quote! {
2476 #(#attrs)*
2477 #[doc = ::core::concat!("Unchecked FFI binding for `", ::core::stringify!(#fn_name), "`.")]
2478 #[doc = #source_loc_doc_lit]
2479 #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
2480 #[link_name = #link_name]
2481 #vis fn #unchecked_name(#inputs) #output;
2482 };
2483 unchecked_items.push(unchecked_fn);
2484
2485 let arg_names: Vec<_> = inputs
2487 .iter()
2488 .filter_map(|arg| {
2489 if let syn::FnArg::Typed(pat_type) = arg
2490 && let syn::Pat::Ident(pat_ident) = pat_type.pat.as_ref()
2491 {
2492 Some(pat_ident.ident.clone())
2493 } else {
2494 None
2495 }
2496 })
2497 .collect();
2498
2499 let is_never = #[allow(non_exhaustive_omitted_patterns)] match output {
syn::ReturnType::Type(_, ty) if
#[allow(non_exhaustive_omitted_patterns)] match **ty {
syn::Type::Never(_) => true,
_ => false,
} => true,
_ => false,
}matches!(output, syn::ReturnType::Type(_, ty) if matches!(**ty, syn::Type::Never(_)));
2500
2501 let wrapper = if is_never {
2502 {
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut attrs, i) = attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let attrs =
match attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&attrs, &mut _s);
}
}
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&checked_doc_lit, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&source_loc_doc_lit, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Generated from source file `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inline");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "always");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "non_snake_case");
_s
});
_s
});
::quote::ToTokens::to_tokens(&vis, &mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&fn_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&inputs, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&output, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "worker");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "with_r_thread");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "move");
::quote::__private::push_or_or(&mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&unchecked_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut arg_names, i) = arg_names.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let arg_names =
match arg_names.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&arg_names, &mut _s);
}
}
_s
});
_s
});
_s
});
_s
});
_s
}quote::quote! {
2504 #(#attrs)*
2505 #[doc = #checked_doc_lit]
2506 #[doc = #source_loc_doc_lit]
2507 #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
2508 #[inline(always)]
2509 #[allow(non_snake_case)]
2510 #vis unsafe fn #fn_name(#inputs) #output {
2511 ::miniextendr_api::worker::with_r_thread(move || unsafe {
2512 #unchecked_name(#(#arg_names),*)
2513 })
2514 }
2515 }
2516 } else {
2517 {
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut attrs, i) = attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let attrs =
match attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&attrs, &mut _s);
}
}
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&checked_doc_lit, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&source_loc_doc_lit, &mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "concat");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"\"Generated from source file `\"");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "file");
::quote::__private::push_bang(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
::quote::__private::parse(&mut _s, "\"`.\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inline");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "always");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "non_snake_case");
_s
});
_s
});
::quote::ToTokens::to_tokens(&vis, &mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&fn_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&inputs, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&output, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "worker");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "with_r_thread");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "move");
::quote::__private::push_or_or(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "worker");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Sendable");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&unchecked_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut arg_names, i) = arg_names.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let arg_names =
match arg_names.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&arg_names, &mut _s);
}
}
_s
});
_s
});
_s
});
_s
});
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_dot(&mut _s);
::quote::__private::parse(&mut _s, "0");
_s
});
_s
}quote::quote! {
2519 #(#attrs)*
2520 #[doc = #checked_doc_lit]
2521 #[doc = #source_loc_doc_lit]
2522 #[doc = ::core::concat!("Generated from source file `", ::core::file!(), "`.")]
2523 #[inline(always)]
2524 #[allow(non_snake_case)]
2525 #vis unsafe fn #fn_name(#inputs) #output {
2526 let result = ::miniextendr_api::worker::with_r_thread(move || {
2527 ::miniextendr_api::worker::Sendable(unsafe {
2528 #unchecked_name(#(#arg_names),*)
2529 })
2530 });
2531 result.0
2532 }
2533 }
2534 };
2535 checked_wrappers.push(wrapper);
2536 }
2537 }
2538 _ => {
2539 unchecked_items.push(item.clone());
2541 }
2542 }
2543 }
2544
2545 let expanded = {
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut foreign_mod_attrs, i) = foreign_mod_attrs.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let foreign_mod_attrs =
match foreign_mod_attrs.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&foreign_mod_attrs, &mut _s);
}
}
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::ToTokens::to_tokens(&abi, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut unchecked_items, i) =
unchecked_items.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let unchecked_items =
match unchecked_items.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&unchecked_items, &mut _s);
}
}
_s
});
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut checked_wrappers, i) = checked_wrappers.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let checked_wrappers =
match checked_wrappers.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&checked_wrappers, &mut _s);
}
}
_s
}quote::quote! {
2546 #(#foreign_mod_attrs)*
2547 unsafe #abi {
2548 #(#unchecked_items)*
2549 }
2550
2551 #(#checked_wrappers)*
2552 };
2553
2554 expanded.into()
2555}
2556
2557#[proc_macro_derive(RNativeType)]
2619pub fn derive_rnative_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2620 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2621 let name = &input.ident;
2622 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
2623
2624 let (inner_ty, elt_ctor): (syn::Type, proc_macro2::TokenStream) = match &input.data {
2626 syn::Data::Struct(data) => match &data.fields {
2627 syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => {
2628 let ty = fields.unnamed.first().unwrap().ty.clone();
2629 let ctor = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "val");
_s
});
_s
}quote::quote! { Self(val) };
2630 (ty, ctor)
2631 }
2632 syn::Fields::Named(fields) if fields.named.len() == 1 => {
2633 let field = fields.named.first().unwrap();
2634 let ty = field.ty.clone();
2635 let field_name = field.ident.as_ref().unwrap();
2636 let ctor = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&field_name, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "val");
_s
});
_s
}quote::quote! { Self { #field_name: val } };
2637 (ty, ctor)
2638 }
2639 _ => {
2640 return syn::Error::new_spanned(
2641 name,
2642 "#[derive(RNativeType)] requires a newtype struct with exactly one field",
2643 )
2644 .into_compile_error()
2645 .into();
2646 }
2647 },
2648 _ => {
2649 return syn::Error::new_spanned(name, "#[derive(RNativeType)] only works on structs")
2650 .into_compile_error()
2651 .into();
2652 }
2653 };
2654
2655 let transparent = input
2658 .attrs
2659 .iter()
2660 .filter(|attr| attr.path().is_ident("repr"))
2661 .any(|attr| {
2662 attr.parse_args_with(
2663 syn::punctuated::Punctuated::<syn::Meta, ::syn::token::Commasyn::Token![,]>::parse_terminated,
2664 )
2665 .is_ok_and(|reprs| reprs.iter().any(|repr| repr.path().is_ident("transparent")))
2666 });
2667 if !transparent {
2668 return syn::Error::new_spanned(
2669 name,
2670 "#[derive(RNativeType)] requires #[repr(transparent)] for native R buffer access",
2671 )
2672 .into_compile_error()
2673 .into();
2674 }
2675
2676 let expanded = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RNativeType");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "SEXP_TYPE");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXPTYPE");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RNativeType");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP_TYPE");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "R_NA");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "val");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RNativeType");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "R_NA");
::quote::__private::push_semi(&mut _s);
::quote::ToTokens::to_tokens(&elt_ctor, &mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inline");
_s
});
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "dataptr_mut");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RNativeType");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "dataptr_mut");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
_s
});
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "cast");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "inline");
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "elt");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "SEXP");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "i");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "isize");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "val");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "RNativeType");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "elt");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "sexp");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "i");
_s
});
::quote::__private::push_semi(&mut _s);
::quote::ToTokens::to_tokens(&elt_ctor, &mut _s);
_s
});
_s
});
_s
}quote::quote! {
2677 impl #impl_generics ::miniextendr_api::RNativeType for #name #ty_generics #where_clause {
2678 const SEXP_TYPE: ::miniextendr_api::SEXPTYPE =
2679 <#inner_ty as ::miniextendr_api::RNativeType>::SEXP_TYPE;
2680
2681 const R_NA: Self = {
2682 let val = <#inner_ty as ::miniextendr_api::RNativeType>::R_NA;
2683 #elt_ctor
2684 };
2685
2686 #[inline]
2687 unsafe fn dataptr_mut(sexp: ::miniextendr_api::SEXP) -> *mut Self {
2688 unsafe {
2690 <#inner_ty as ::miniextendr_api::RNativeType>::dataptr_mut(sexp).cast()
2691 }
2692 }
2693
2694 #[inline]
2695 fn elt(sexp: ::miniextendr_api::SEXP, i: isize) -> Self {
2696 let val = <#inner_ty as ::miniextendr_api::RNativeType>::elt(sexp, i);
2697 #elt_ctor
2698 }
2699 }
2700
2701 };
2702
2703 expanded.into()
2704}
2705
2706#[proc_macro_derive(IsNA)]
2738pub fn derive_is_na(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2739 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2740 newtype_derive::derive_is_na(input)
2741 .unwrap_or_else(|e| e.into_compile_error())
2742 .into()
2743}
2744
2745#[proc_macro_derive(ExternalPtr, attributes(externalptr, r_data))]
2798pub fn derive_external_ptr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2799 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2800
2801 externalptr_derive::derive_external_ptr(input, true)
2805 .unwrap_or_else(|e| e.into_compile_error())
2806 .into()
2807}
2808
2809#[proc_macro_derive(AllEqual, attributes(all_equal))]
2900pub fn derive_all_equal(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2901 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2902 all_equal_derive::derive_all_equal(input)
2903 .unwrap_or_else(|e| e.into_compile_error())
2904 .into()
2905}
2906
2907#[proc_macro_derive(AltrepInteger, attributes(altrep, r_data))]
2957pub fn derive_altrep_integer(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2958 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2959 altrep_derive::derive_altrep_integer(input)
2960 .unwrap_or_else(|e| e.into_compile_error())
2961 .into()
2962}
2963
2964#[proc_macro_derive(AltrepReal, attributes(altrep, r_data))]
2969pub fn derive_altrep_real(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2970 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2971 altrep_derive::derive_altrep_real(input)
2972 .unwrap_or_else(|e| e.into_compile_error())
2973 .into()
2974}
2975
2976#[proc_macro_derive(AltrepLogical, attributes(altrep, r_data))]
2981pub fn derive_altrep_logical(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2982 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2983 altrep_derive::derive_altrep_logical(input)
2984 .unwrap_or_else(|e| e.into_compile_error())
2985 .into()
2986}
2987
2988#[proc_macro_derive(AltrepRaw, attributes(altrep, r_data))]
2993pub fn derive_altrep_raw(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
2994 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
2995 altrep_derive::derive_altrep_raw(input)
2996 .unwrap_or_else(|e| e.into_compile_error())
2997 .into()
2998}
2999
3000#[proc_macro_derive(AltrepString, attributes(altrep, r_data))]
3005pub fn derive_altrep_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3006 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3007 altrep_derive::derive_altrep_string(input)
3008 .unwrap_or_else(|e| e.into_compile_error())
3009 .into()
3010}
3011
3012#[proc_macro_derive(AltrepComplex, attributes(altrep, r_data))]
3017pub fn derive_altrep_complex(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3018 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3019 altrep_derive::derive_altrep_complex(input)
3020 .unwrap_or_else(|e| e.into_compile_error())
3021 .into()
3022}
3023
3024#[proc_macro_derive(AltrepList, attributes(altrep, r_data))]
3033pub fn derive_altrep_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3034 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3035 altrep_derive::derive_altrep_list(input)
3036 .unwrap_or_else(|e| e.into_compile_error())
3037 .into()
3038}
3039
3040#[proc_macro_derive(Altrep, attributes(altrep, r_data))]
3067pub fn derive_altrep(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3068 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3069 altrep::derive_altrep(input)
3070 .unwrap_or_else(|e| e.into_compile_error())
3071 .into()
3072}
3073
3074#[proc_macro_derive(IntoList, attributes(into_list))]
3080pub fn derive_into_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3081 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3082 list_derive::derive_into_list(input)
3083 .unwrap_or_else(|e| e.into_compile_error())
3084 .into()
3085}
3086
3087#[proc_macro_derive(TryFromList, attributes(into_list))]
3097pub fn derive_try_from_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3098 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3099 list_derive::derive_try_from_list(input)
3100 .unwrap_or_else(|e| e.into_compile_error())
3101 .into()
3102}
3103
3104#[proc_macro_derive(PreferList)]
3123pub fn derive_prefer_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3124 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3125 list_derive::derive_prefer_list(input)
3126 .unwrap_or_else(|e| e.into_compile_error())
3127 .into()
3128}
3129
3130#[proc_macro_derive(PreferExternalPtr)]
3147pub fn derive_prefer_externalptr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3148 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3149 list_derive::derive_prefer_externalptr(input)
3150 .unwrap_or_else(|e| e.into_compile_error())
3151 .into()
3152}
3153
3154#[proc_macro_derive(PreferRNativeType)]
3167pub fn derive_prefer_rnative(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3168 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3169 list_derive::derive_prefer_rnative(input)
3170 .unwrap_or_else(|e| e.into_compile_error())
3171 .into()
3172}
3173
3174#[cfg(feature = "vctrs")]
3189#[proc_macro_derive(PreferVctrs)]
3190pub fn derive_prefer_vctrs(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3191 let input = syn::parse_macro_input!(input as syn::DeriveInput);
3192 list_derive::derive_prefer_vctrs(input)
3193 .unwrap_or_else(|e| e.into_compile_error())
3194 .into()
3195}
3196
3197#[proc_macro_derive(DataFrameRow, attributes(dataframe))]
3282pub fn derive_dataframe_row(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3283 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3284 dataframe_derive::derive_dataframe_row(input)
3285 .unwrap_or_else(|e| e.into_compile_error())
3286 .into()
3287}
3288
3289#[proc_macro_derive(RFactor, attributes(r_factor))]
3312pub fn derive_r_factor(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3313 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3314 factor_derive::derive_r_factor(input)
3315 .unwrap_or_else(|e| e.into_compile_error())
3316 .into()
3317}
3318
3319#[proc_macro_derive(MatchArg, attributes(match_arg))]
3351pub fn derive_match_arg(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3352 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3353 match_arg_derive::derive_match_arg(input)
3354 .unwrap_or_else(|e| e.into_compile_error())
3355 .into()
3356}
3357
3358#[proc_macro_derive(RCondition, attributes(condition))]
3385pub fn derive_r_condition(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3386 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3387 condition_derive::derive_r_condition(input)
3388 .unwrap_or_else(|e| e.into_compile_error())
3389 .into()
3390}
3391
3392#[proc_macro_derive(TryFromSexp, attributes(try_from_sexp))]
3454pub fn derive_try_from_sexp(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3455 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3456 newtype_derive::derive_try_from_sexp(input)
3457 .unwrap_or_else(|e| e.into_compile_error())
3458 .into()
3459}
3460
3461#[proc_macro_derive(IntoR)]
3472pub fn derive_into_r(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3473 let input = match ::syn::parse::<syn::DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::DeriveInput);
3474 newtype_derive::derive_into_r(input)
3475 .unwrap_or_else(|e| e.into_compile_error())
3476 .into()
3477}
3478
3479#[cfg(feature = "vctrs")]
3503#[proc_macro_derive(Vctrs, attributes(vctrs))]
3504pub fn derive_vctrs(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3505 let input = syn::parse_macro_input!(input as syn::DeriveInput);
3506 vctrs_derive::derive_vctrs(input)
3507 .unwrap_or_else(|e| e.into_compile_error())
3508 .into()
3509}
3510
3511#[proc_macro]
3627pub fn typed_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3628 let parsed = match ::syn::parse::<typed_list::TypedListInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as typed_list::TypedListInput);
3629 typed_list::expand_typed_list(parsed).into()
3630}
3631
3632#[proc_macro]
3722pub fn typed_dataframe(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3723 let parsed = match ::syn::parse::<typed_dataframe::TypedDataframeInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as typed_dataframe::TypedDataframeInput);
3724 typed_dataframe::expand_typed_dataframe(parsed).into()
3725}
3726
3727#[proc_macro]
3770pub fn list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3771 let parsed = match ::syn::parse::<list_macro::ListInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as list_macro::ListInput);
3772 list_macro::expand_list(parsed).into()
3773}
3774
3775#[proc_macro]
3833pub fn r(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3834 r_macro::expand(input)
3835}
3836
3837#[proc_macro]
3878pub fn reexport(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3879 reexport::expand(input.into()).into()
3880}
3881
3882#[proc_macro]
3887#[doc(hidden)]
3888pub fn __mx_trait_impl_expand(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3889 miniextendr_impl_trait::expand_tpie(input)
3890}
3891
3892#[proc_macro]
3907pub fn impl_typed_external(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3908 match typed_external_macro::impl_typed_external(input.into()) {
3909 Ok(tokens) => tokens.into(),
3910 Err(err) => err.into_compile_error().into(),
3911 }
3912}
3913
3914#[proc_macro]
3939pub fn miniextendr_init(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3940 let pkg_name: syn::Ident = if input.is_empty() {
3941 let name = match std::env::var("CARGO_CRATE_NAME") {
3946 Ok(n) => n,
3947 Err(_) => {
3948 return syn::Error::new(
3949 proc_macro2::Span::call_site(),
3950 "CARGO_CRATE_NAME not set. Either pass the package name explicitly: \
3951 miniextendr_init!(mypkg), or ensure you're building with cargo.",
3952 )
3953 .into_compile_error()
3954 .into();
3955 }
3956 };
3957 match syn::parse_str::<syn::Ident>(&name) {
3958 Ok(id) => id,
3959 Err(_) => {
3960 return syn::Error::new(
3961 proc_macro2::Span::call_site(),
3962 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CARGO_CRATE_NAME `{0}` is not a valid C identifier; R_init_<pkg> must match `[A-Za-z_][A-Za-z0-9_]*`. Pass the name explicitly: miniextendr_init!(my_pkg).",
name))
})format!(
3963 "CARGO_CRATE_NAME `{name}` is not a valid C identifier; \
3964 R_init_<pkg> must match `[A-Za-z_][A-Za-z0-9_]*`. \
3965 Pass the name explicitly: miniextendr_init!(my_pkg)."
3966 ),
3967 )
3968 .into_compile_error()
3969 .into();
3970 }
3971 }
3972 } else {
3973 match ::syn::parse::<syn::Ident>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}syn::parse_macro_input!(input as syn::Ident)
3974 };
3975 let fn_name = syn::Ident::new(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("R_init_{0}", pkg_name))
})format!("R_init_{}", pkg_name), pkg_name.span());
3976 let unload_name = syn::Ident::new(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("R_unload_{0}", pkg_name))
})format!("R_unload_{}", pkg_name), pkg_name.span());
3977
3978 let mut name_bytes = pkg_name.to_string().into_bytes();
3980 name_bytes.push(0);
3981 let byte_lit = syn::LitByteStr::new(&name_bytes, pkg_name.span());
3982
3983 let conversion_error_class = crate::crate_config::conversion_error_class();
3987 let init_marker = crate::miniextendr_fn::init_marker_ident();
3988
3989 let expanded = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" The crate\'s marker type. A `serde_error_shape!` declaration is an\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" impl keyed by it, and the generated `Err` arms look the declaration\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" up under it, so the macro must be called at the crate root.\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "pub");
::quote::__private::push_ident(&mut _s, "enum");
::quote::ToTokens::to_tokens(&init_marker, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
::quote::__private::TokenStream::new());
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" The package crate\'s `conversion_error_class`, read by the\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" wrapper-generation pass and the raising guards (host-only; the\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" `wasm_registry.rs` snapshot carries it to wasm32).\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "cfg");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "not");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "target_arch");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm32\"");
_s
});
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "distributed_slice");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"MX_CONVERSION_ERROR_CLASS");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "linkme");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "crate");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "linkme");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "static");
::quote::__private::push_ident(&mut _s, "__MX_CONVERSION_ERROR_CLASS");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ConversionErrorClassEntry");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ConversionErrorClassEntry");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "classes");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut conversion_error_class, i) =
conversion_error_class.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let conversion_error_class =
match conversion_error_class.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::ToTokens::to_tokens(&conversion_error_class,
&mut _s);
}
}
_s
});
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "cfg");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "target_arch");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm32\"");
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "path");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm_registry.rs\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "hidden");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "mod");
::quote::__private::push_ident(&mut _s, "__miniextendr_wasm_registry");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "no_mangle");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "pub");
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "extern");
::quote::__private::parse(&mut _s, "\"C-unwind\"");
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&fn_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "dll");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sys");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "DllInfo");
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s,
"__miniextendr_init_result");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "panic");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "catch_unwind");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "panic");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AssertUnwindSafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or_or(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "cfg");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "target_arch");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "\"wasm32\"");
_s
});
_s
});
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"install_wasm_runtime_slices");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"__miniextendr_wasm_registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"MX_CALL_DEFS_WASM");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"__miniextendr_wasm_registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"MX_ALTREP_REGISTRATIONS_WASM");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"__miniextendr_wasm_registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"MX_TRAIT_DISPATCH_WASM");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"__miniextendr_wasm_registry");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"MX_CONVERSION_ERROR_CLASS_WASM");
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_ident(&mut _s, "pkg_name");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ffi");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "CStr");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"from_bytes_with_nul_unchecked");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&byte_lit, &mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "init");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "package_init");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "dll");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "pkg_name");
_s
});
::quote::__private::push_semi(&mut _s);
_s
});
_s
});
_s
});
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "if");
::quote::__private::push_ident(&mut _s, "let");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Result");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Err");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "payload");
_s
});
::quote::__private::push_eq(&mut _s);
::quote::__private::push_ident(&mut _s,
"__miniextendr_init_result");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "core");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "mem");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "drop");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "payload");
_s
});
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sys");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"Rf_error_unchecked");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::parse(&mut _s,
"c\"miniextendr package initialization panicked before completing\"");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "as_ptr");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_semi(&mut _s);
_s
});
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" R_unload_<pkg> entry point \u{2014} R calls this on `detach(unload=TRUE)` /\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" `dyn.unload()`. Signals the miniextendr worker thread (if enabled)\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" to exit cleanly. See `#103`.\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "no_mangle");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "pub");
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_ident(&mut _s, "extern");
::quote::__private::parse(&mut _s, "\"C-unwind\"");
::quote::__private::push_ident(&mut _s, "fn");
::quote::ToTokens::to_tokens(&unload_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "_dll");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "mut");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "sys");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "DllInfo");
::quote::__private::push_comma(&mut _s);
_s
});
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "miniextendr_api");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "worker");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"miniextendr_runtime_shutdown");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_semi(&mut _s);
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" Linker anchor: stub.c takes the address of this symbol to force the\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" linker to pull in the user crate\'s archive member from the staticlib.\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" With codegen-units = 1, this single member contains all linkme\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" distributed_slice entries. The name is package-independent so stub.c\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" doesn\'t need configure substitution.\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s, "r\"\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" Defined as a function rather than a static so it stays exported under\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" the webR wasm RUSTFLAG -Zdefault-visibility=hidden, which keeps\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" no_mangle functions exported (like the R_init entry point) but hides\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" no_mangle statics. A hidden anchor breaks wasm side-module dlopen\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "doc");
::quote::__private::push_eq(&mut _s);
::quote::__private::parse(&mut _s,
"r\" (bad export type, undefined). See miniextendr webR notes (#494).\"");
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "unsafe");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "no_mangle");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "pub");
::quote::__private::push_ident(&mut _s, "extern");
::quote::__private::parse(&mut _s, "\"C\"");
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "miniextendr_force_link");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
::quote::__private::TokenStream::new());
_s
}quote::quote! {
3990 #[doc(hidden)]
3994 pub enum #init_marker {}
3995
3996 #[cfg(not(target_arch = "wasm32"))]
4000 #[::miniextendr_api::linkme::distributed_slice(::miniextendr_api::registry::MX_CONVERSION_ERROR_CLASS)]
4001 #[linkme(crate = ::miniextendr_api::linkme)]
4002 #[doc(hidden)]
4003 static __MX_CONVERSION_ERROR_CLASS: ::miniextendr_api::registry::ConversionErrorClassEntry =
4004 ::miniextendr_api::registry::ConversionErrorClassEntry {
4005 classes: &[#(#conversion_error_class),*],
4006 };
4007
4008 #[cfg(target_arch = "wasm32")]
4017 #[path = "wasm_registry.rs"]
4018 #[doc(hidden)]
4019 mod __miniextendr_wasm_registry;
4020
4021 #[unsafe(no_mangle)]
4022 pub unsafe extern "C-unwind" fn #fn_name(
4023 dll: *mut ::miniextendr_api::sys::DllInfo,
4024 ) {
4025 let __miniextendr_init_result = ::std::panic::catch_unwind(
4026 ::std::panic::AssertUnwindSafe(|| {
4027 #[cfg(target_arch = "wasm32")]
4033 ::miniextendr_api::registry::install_wasm_runtime_slices(
4034 __miniextendr_wasm_registry::MX_CALL_DEFS_WASM,
4035 __miniextendr_wasm_registry::MX_ALTREP_REGISTRATIONS_WASM,
4036 __miniextendr_wasm_registry::MX_TRAIT_DISPATCH_WASM,
4037 __miniextendr_wasm_registry::MX_CONVERSION_ERROR_CLASS_WASM,
4038 );
4039
4040 unsafe {
4041 let pkg_name = ::std::ffi::CStr::from_bytes_with_nul_unchecked(#byte_lit);
4043 ::miniextendr_api::init::package_init(dll, pkg_name);
4044 }
4045 }),
4046 );
4047 if let ::core::result::Result::Err(payload) = __miniextendr_init_result {
4048 ::core::mem::drop(payload);
4052 unsafe {
4053 ::miniextendr_api::sys::Rf_error_unchecked(
4054 c"miniextendr package initialization panicked before completing".as_ptr(),
4055 );
4056 }
4057 }
4058 }
4059
4060 #[unsafe(no_mangle)]
4064 pub unsafe extern "C-unwind" fn #unload_name(
4065 _dll: *mut ::miniextendr_api::sys::DllInfo,
4066 ) {
4067 ::miniextendr_api::worker::miniextendr_runtime_shutdown();
4068 }
4069
4070 #[unsafe(no_mangle)]
4082 pub extern "C" fn miniextendr_force_link() {}
4083 };
4084
4085 expanded.into()
4086}
4087
4088#[cfg(test)]
4089mod tests;