1use proc_macro2::TokenStream;
23use quote::{format_ident, quote, quote_spanned};
24use syn::spanned::Spanned;
25
26#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Mode { }
#[automatically_derived]
impl ::core::clone::Clone for Mode {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Mode { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Mode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Mode::Shared => "Shared",
Mode::Exclusive => "Exclusive",
Mode::SharedView => "SharedView",
Mode::ExclusiveView => "ExclusiveView",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Mode { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Mode {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Mode { }Eq)]
28pub(crate) enum Mode {
29 Shared,
31 Exclusive,
33 SharedView,
35 ExclusiveView,
37}
38
39impl Mode {
40 fn is_exclusive(self) -> bool {
41 #[allow(non_exhaustive_omitted_patterns)] match self {
Mode::Exclusive | Mode::ExclusiveView => true,
_ => false,
}matches!(self, Mode::Exclusive | Mode::ExclusiveView)
42 }
43}
44
45#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ExternalArg {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "ExternalArg",
"value", &self.value, "optional", &self.optional, "mode",
&&self.mode)
}
}Debug)]
47pub(crate) struct ExternalArg {
48 pub value: syn::Type,
50 pub optional: bool,
52 pub mode: Mode,
53}
54
55const NOT_EXTERNAL: &[&str] = &[
59 "str",
60 "Path",
61 "Dots",
62 "LazyDots",
63 "RngGuard",
64 "SEXP",
65 "i32",
66 "f64",
67 "u8",
68 "RLogical",
69 "Rcomplex",
70 "Option",
71 "Vec",
72 "Box",
73 "Rc",
74 "Arc",
75 "Cow",
76 "Result",
77 "ExternalPtr",
78 "ExternalPtrRef",
79 "ExternalPtrMut",
80 "Missing",
81];
82
83pub(crate) fn external_arg(ty: &syn::Type) -> Option<ExternalArg> {
90 let (inner, optional) = match crate::type_inspect::option_inner_type(ty) {
91 Some(inner) => (inner, true),
92 None => (ty, false),
93 };
94 let (value, mode) = match inner {
95 syn::Type::Reference(reference) if is_external_value(&reference.elem) => {
96 let mode = if reference.mutability.is_some() {
97 Mode::Exclusive
98 } else {
99 Mode::Shared
100 };
101 (reference.elem.as_ref().clone(), mode)
102 }
103 syn::Type::Path(path) if path.qself.is_none() => {
104 let seg = path.path.segments.last()?;
105 let mode = if seg.ident == "ExternalPtrRef" {
106 Mode::SharedView
107 } else if seg.ident == "ExternalPtrMut" {
108 Mode::ExclusiveView
109 } else {
110 return None;
111 };
112 (crate::type_inspect::first_type_argument(seg)?.clone(), mode)
113 }
114 _ => return None,
115 };
116 Some(ExternalArg {
117 value,
118 optional,
119 mode,
120 })
121}
122
123fn is_external_value(ty: &syn::Type) -> bool {
124 let syn::Type::Path(path) = ty else {
125 return false;
126 };
127 path.qself.is_none()
128 && path.path.segments.last().is_some_and(|seg| {
129 !NOT_EXTERNAL.contains(&seg.ident.to_string().as_str())
130 && !crate::r_preconditions::has_type_check(ty)
131 })
132}
133
134pub(crate) fn handle_ident(param: &syn::Ident) -> syn::Ident {
137 match ::quote::__private::IdentFragmentAdapter(&crate::naming::unraw(param)) {
arg =>
::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__mx_ptr_{0}", arg))
}),
::quote::__private::Option::Some::<::quote::__private::Span>(proc_macro2::Span::mixed_site())),
}format_ident!(
138 "__mx_ptr_{}",
139 crate::naming::unraw(param),
140 span = proc_macro2::Span::mixed_site()
141 )
142}
143
144pub(crate) fn replace_self(ty: &syn::Type, self_ty: Option<&syn::Type>) -> syn::Type {
147 match (ty, self_ty) {
148 (syn::Type::Path(path), Some(self_ty)) if path.path.is_ident("Self") => self_ty.clone(),
149 _ => ty.clone(),
150 }
151}
152
153pub(crate) fn handle_conversion(
157 ident: &syn::Ident,
158 sexp_ident: &syn::Ident,
159 ty: &syn::Type,
160 arg: &ExternalArg,
161 self_ty: Option<&syn::Type>,
162 err_arm: TokenStream,
163) -> TokenStream {
164 let handle = handle_ident(ident);
165 if let Some(lifetime) = crate::type_inspect::static_lifetime(ty) {
166 return {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(lifetime.span()).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "compile_error");
::quote::__private::push_bang_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::parse_spanned(&mut _s, _span,
"\"this parameter borrows its object for the call and cannot be `\'static`; \\\n elide the lifetime, or take `ExternalPtr<T>` to keep a handle\"");
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&ident, &mut _s);
::quote::__private::push_colon_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "None");
::quote::__private::push_dot_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "unwrap");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let _: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::TokenStream::new()
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {lifetime.span()=>
167 ::core::compile_error!(
168 "this parameter borrows its object for the call and cannot be `'static`; \
169 elide the lifetime, or take `ExternalPtr<T>` to keep a handle"
170 );
171 let #ident: #ty = ::core::option::Option::<#ty>::None.unwrap();
172 };
173 }
174 let value = replace_self(&arg.value, self_ty);
175 let span = arg.value.span();
176 let convert = if arg.optional {
177 {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_optional_external_arg");
_s
}quote_spanned! {span=> __mx_optional_external_arg }
178 } else {
179 {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_external_arg");
_s
}quote_spanned! {span=> __mx_external_arg }
180 };
181 let mutability = arg.mode.is_exclusive().then(|| {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "mut");
_s
}quote! { mut });
182 {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&mutability, &mut _s);
::quote::ToTokens::to_tokens(&handle, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "match");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "miniextendr_api");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "from_r");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&convert, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::ToTokens::to_tokens(&sexp_ident, &mut _s);
_s
});
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "result");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Result");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Ok");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "v");
_s
});
::quote::__private::push_fat_arrow_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "v");
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&err_arm, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
185 let #mutability #handle = match ::miniextendr_api::from_r::#convert::<#value>(#sexp_ident) {
186 ::core::result::Result::Ok(v) => v,
187 #err_arm
188 };
189 }
190}
191
192pub(crate) fn arg_borrows(
197 inputs: &syn::punctuated::Punctuated<syn::FnArg, ::syn::token::Commasyn::Token![,]>,
198 unborrowed: &[String],
199 self_ty: Option<&syn::Type>,
200) -> TokenStream {
201 let mut borrows = TokenStream::new();
202 for arg in inputs {
203 let syn::FnArg::Typed(pt) = arg else {
204 continue;
205 };
206 let syn::Pat::Ident(pat) = pt.pat.as_ref() else {
207 continue;
208 };
209 let Some(external) = external_arg(&pt.ty) else {
210 continue;
211 };
212 if unborrowed.contains(&crate::naming::ident_name(&pat.ident)) {
213 continue;
214 }
215 let name = &pat.ident;
216 let handle = handle_ident(name);
217 let guard = match ::quote::__private::IdentFragmentAdapter(&crate::naming::unraw(name)) {
arg =>
::quote::__private::mk_ident(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__mx_guard_{0}", arg))
}),
::quote::__private::Option::Some::<::quote::__private::Span>(proc_macro2::Span::mixed_site())),
}format_ident!(
218 "__mx_guard_{}",
219 crate::naming::unraw(name),
220 span = proc_macro2::Span::mixed_site()
221 );
222 let value = replace_self(&external.value, self_ty);
223 let span = external.value.span();
224 let api = {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "miniextendr_api");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "externalptr");
_s
}quote_spanned! {span=> ::miniextendr_api::externalptr };
225 borrows.extend(match (external.mode, external.optional) {
226 (Mode::Shared, false) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&guard, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_borrow");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_shared");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&guard, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
227 let #guard = #api::__mx_borrow::<#value>(&#handle);
228 let #name = #api::__mx_shared::<#value>(&#guard);
229 },
230 (Mode::Exclusive, false) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::__private::push_ident_spanned(&mut _s, _span, "mut");
::quote::ToTokens::to_tokens(&guard, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_borrow_mut");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "mut");
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_exclusive");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "mut");
::quote::ToTokens::to_tokens(&guard, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
231 let mut #guard = #api::__mx_borrow_mut::<#value>(&mut #handle);
232 let #name = #api::__mx_exclusive::<#value>(&mut #guard);
233 },
234 (Mode::SharedView, false) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_borrow");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
235 let #name = #api::__mx_borrow::<#value>(&#handle);
236 },
237 (Mode::ExclusiveView, false) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "__mx_borrow_mut");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "mut");
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
238 let #name = #api::__mx_borrow_mut::<#value>(&mut #handle);
239 },
240 (Mode::Shared, true) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&guard, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_ref");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_borrow");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_ref");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&guard, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_shared");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
241 let #guard = ::core::option::Option::map(
242 ::core::option::Option::as_ref(&#handle), #api::__mx_borrow::<#value>,
243 );
244 let #name = ::core::option::Option::map(
245 ::core::option::Option::as_ref(&#guard), #api::__mx_shared::<#value>,
246 );
247 },
248 (Mode::Exclusive, true) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::__private::push_ident_spanned(&mut _s, _span, "mut");
::quote::ToTokens::to_tokens(&guard, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_mut");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"mut");
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_borrow_mut");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_mut");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"mut");
::quote::ToTokens::to_tokens(&guard, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_exclusive");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
249 let mut #guard = ::core::option::Option::map(
250 ::core::option::Option::as_mut(&mut #handle), #api::__mx_borrow_mut::<#value>,
251 );
252 let #name = ::core::option::Option::map(
253 ::core::option::Option::as_mut(&mut #guard), #api::__mx_exclusive::<#value>,
254 );
255 },
256 (Mode::SharedView, true) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_ref");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_borrow");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
257 let #name = ::core::option::Option::map(
258 ::core::option::Option::as_ref(&#handle), #api::__mx_borrow::<#value>,
259 );
260 },
261 (Mode::ExclusiveView, true) => {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::__private::push_ident_spanned(&mut _s, _span, "let");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_eq_spanned(&mut _s, _span);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "map");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "core");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "Option");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "as_mut");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::__private::push_and_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"mut");
::quote::ToTokens::to_tokens(&handle, &mut _s);
_s
});
::quote::__private::push_comma_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&api, &mut _s);
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"__mx_borrow_mut");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_lt_spanned(&mut _s, _span);
::quote::ToTokens::to_tokens(&value, &mut _s);
::quote::__private::push_gt_spanned(&mut _s, _span);
::quote::__private::push_comma_spanned(&mut _s, _span);
_s
});
::quote::__private::push_semi_spanned(&mut _s, _span);
_s
}quote_spanned! {span=>
262 let #name = ::core::option::Option::map(
263 ::core::option::Option::as_mut(&mut #handle), #api::__mx_borrow_mut::<#value>,
264 );
265 },
266 });
267 }
268 borrows
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274
275 fn arg(ty: syn::Type) -> Option<(String, bool, Mode)> {
276 external_arg(&ty).map(|arg| {
277 let value = &arg.value;
278 (quote!(#value).to_string(), arg.optional, arg.mode)
279 })
280 }
281
282 #[test]
283 fn references_to_types_without_conversions_and_views_are_external() {
284 let some = |value: &str, optional, mode| Some((value.to_owned(), optional, mode));
285 assert_eq!(
286 arg(syn::parse_quote!(&Counter)),
287 some("Counter", false, Mode::Shared)
288 );
289 assert_eq!(
290 arg(syn::parse_quote!(&mut crate::Counter)),
291 some("crate :: Counter", false, Mode::Exclusive)
292 );
293 assert_eq!(
294 arg(syn::parse_quote!(&'a Self)),
295 some("Self", false, Mode::Shared)
296 );
297 assert_eq!(
298 arg(syn::parse_quote!(Option<&mut Counter>)),
299 some("Counter", true, Mode::Exclusive)
300 );
301 assert_eq!(
302 arg(syn::parse_quote!(ExternalPtrRef<'_, Counter>)),
303 some("Counter", false, Mode::SharedView)
304 );
305 assert_eq!(
306 arg(syn::parse_quote!(
307 Option<::miniextendr_api::ExternalPtrMut<'a, Counter>>
308 )),
309 some("Counter", true, Mode::ExclusiveView)
310 );
311 }
312
313 #[test]
314 fn native_string_dots_container_and_handle_types_are_not_external() {
315 for ty in [
316 quote!(&str),
317 quote!(&Path),
318 quote!(&i32),
319 quote!(&mut f64),
320 quote!(&RLogical),
321 quote!(&[i32]),
322 quote!(&mut [f64]),
323 quote!(&Dots),
324 quote!(&String),
325 quote!(&Vec<i32>),
326 quote!(&Option<Counter>),
327 quote!(&ExternalPtr<Counter>),
328 quote!(ExternalPtr<Counter>),
329 quote!(Option<ExternalPtr<Counter>>),
330 quote!(Vec<&Counter>),
331 quote!(Counter),
332 ] {
333 let ty: syn::Type = syn::parse2(ty).unwrap();
334 assert!(external_arg(&ty).is_none(), "{}", quote!(#ty));
335 }
336 }
337
338 #[test]
339 fn borrows_follow_the_mode() {
340 let sig: syn::Signature = syn::parse_quote!(fn f(
341 a: &mut Counter,
342 b: Option<&Counter>,
343 n: i32,
344 c: ExternalPtr<Counter>,
345 d: ExternalPtrRef<'_, Counter>,
346 e: Option<ExternalPtrMut<'_, Counter>>,
347 m: &Counter,
348 ));
349 let borrow = arg_borrows(&sig.inputs, &["m".to_owned()], None).to_string();
350 assert!(
351 borrow.contains("let a = :: miniextendr_api :: externalptr :: __mx_exclusive :: < Counter > (& mut __mx_guard_a)"),
352 "{borrow}"
353 );
354 assert!(borrow.contains("__mx_shared"), "{borrow}");
355 assert!(
356 borrow.contains("let d = :: miniextendr_api :: externalptr :: __mx_borrow :: < Counter > (& __mx_ptr_d)"),
357 "{borrow}"
358 );
359 assert!(
360 borrow.contains("let e = :: core :: option :: Option :: map"),
361 "{borrow}"
362 );
363 assert_eq!(borrow.matches("__mx_borrow_mut").count(), 2, "{borrow}");
364 assert!(
365 !borrow.contains("__mx_ptr_c") && !borrow.contains("__mx_ptr_n"),
366 "{borrow}"
367 );
368 assert!(!borrow.contains("__mx_ptr_m"), "{borrow}");
369 }
370
371 #[test]
372 fn handle_conversion_names_the_concrete_type_and_mutability() {
373 let ident: syn::Ident = syn::parse_quote!(other);
374 let sexp: syn::Ident = syn::parse_quote!(arg_0);
375 let ty: syn::Type = syn::parse_quote!(&mut Self);
376 let arg = external_arg(&ty).unwrap();
377 let self_ty: syn::Type = syn::parse_quote!(Counter);
378 let stmt =
379 handle_conversion(&ident, &sexp, &ty, &arg, Some(&self_ty), quote! {}).to_string();
380 assert!(stmt.contains("let mut __mx_ptr_other"), "{stmt}");
381 assert!(
382 stmt.contains("__mx_external_arg :: < Counter > (arg_0)"),
383 "{stmt}"
384 );
385
386 let ty: syn::Type = syn::parse_quote!(&'static Counter);
387 let arg = external_arg(&ty).unwrap();
388 let stmt = handle_conversion(&ident, &sexp, &ty, &arg, None, quote! {}).to_string();
389 assert!(stmt.contains("compile_error"), "{stmt}");
390 }
391}