1use crate::syntax::atom::Atom::*;
2use crate::syntax::attrs::{self, OtherAttrs};
3use crate::syntax::cfg::CfgExpr;
4use crate::syntax::file::Module;
5use crate::syntax::instantiate::{ImplKey, NamedImplKey};
6use crate::syntax::qualified::QualifiedName;
7use crate::syntax::report::Errors;
8use crate::syntax::symbol::Symbol;
9use crate::syntax::{
10 self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
11 Struct, Trait, Type, TypeAlias, Types,
12};
13use crate::type_id::Crate;
14use crate::{derive, generics};
15use proc_macro2::{Ident, Span, TokenStream};
16use quote::{format_ident, quote, quote_spanned, ToTokens};
17use std::mem;
18use syn::{parse_quote, punctuated, Generics, Lifetime, Result, Token};
19
20pub(crate) fn bridge(mut ffi: Module) -> Result<TokenStream> {
21 let ref mut errors = Errors::new();
22
23 let mut cfg = CfgExpr::Unconditional;
24 let mut doc = Doc::new();
25 let attrs = attrs::parse(
26 errors,
27 mem::take(&mut ffi.attrs),
28 attrs::Parser {
29 cfg: Some(&mut cfg),
30 doc: Some(&mut doc),
31 ..Default::default()
32 },
33 );
34
35 let content = mem::take(&mut ffi.content);
36 let trusted = ffi.unsafety.is_some();
37 let namespace = &ffi.namespace;
38 let ref mut apis = syntax::parse_items(errors, content, trusted, namespace);
39 #[cfg(feature = "experimental-enum-variants-from-header")]
40 crate::load::load(errors, apis);
41 let ref types = Types::collect(errors, apis);
42 errors.propagate()?;
43
44 let generator = check::Generator::Macro;
45 check::typecheck(errors, apis, types, generator);
46 errors.propagate()?;
47
48 Ok(expand(ffi, doc, attrs, apis, types))
49}
50
51fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
52 let mut expanded = TokenStream::new();
53 let mut hidden = TokenStream::new();
54 let mut forbid = TokenStream::new();
55
56 for api in apis {
57 if let Api::RustType(ety) = api {
58 expanded.extend(expand_rust_type_import(ety));
59 hidden.extend(expand_rust_type_assert_unpin(ety, types));
60 }
61 }
62
63 for api in apis {
64 match api {
65 Api::Include(_) | Api::Impl(_) => {}
66 Api::Struct(strct) => {
67 expanded.extend(expand_struct(strct));
68 hidden.extend(expand_struct_operators(strct));
69 forbid.extend(expand_struct_forbid_drop(strct));
70 }
71 Api::Enum(enm) => expanded.extend(expand_enum(enm)),
72 Api::CxxType(ety) => {
73 let ident = &ety.name.rust;
74 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
75 expanded.extend(expand_cxx_type(ety));
76 hidden.extend(expand_cxx_type_assert_pinned(ety, types));
77 }
78 }
79 Api::CxxFunction(efn) => {
80 expanded.extend(expand_cxx_function_shim(efn, types));
81 }
82 Api::RustType(ety) => {
83 expanded.extend(expand_rust_type_impl(ety));
84 hidden.extend(expand_rust_type_layout(ety, types));
85 }
86 Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
87 Api::TypeAlias(alias) => {
88 expanded.extend(expand_type_alias(alias));
89 hidden.extend(expand_type_alias_verify(alias, types));
90 }
91 }
92 }
93
94 for (impl_key, &explicit_impl) in &types.impls {
95 match *impl_key {
96 ImplKey::RustBox(ident) => {
97 hidden.extend(expand_rust_box(ident, types, explicit_impl));
98 }
99 ImplKey::RustVec(ident) => {
100 hidden.extend(expand_rust_vec(ident, types, explicit_impl));
101 }
102 ImplKey::UniquePtr(ident) => {
103 expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
104 }
105 ImplKey::SharedPtr(ident) => {
106 expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
107 }
108 ImplKey::WeakPtr(ident) => {
109 expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
110 }
111 ImplKey::CxxVector(ident) => {
112 expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
113 }
114 }
115 }
116
117 if !forbid.is_empty() {
118 hidden.extend(expand_forbid(forbid));
119 }
120
121 if !hidden.is_empty() {
123 expanded.extend(quote! {
124 #[doc(hidden)]
125 const _: () = {
126 #hidden
127 };
128 });
129 }
130
131 let vis = &ffi.vis;
132 let mod_token = &ffi.mod_token;
133 let ident = &ffi.ident;
134 let span = ffi.brace_token.span;
135 let expanded = quote_spanned!(span=> {#expanded});
136
137 quote! {
138 #doc
139 #attrs
140 #[deny(improper_ctypes, improper_ctypes_definitions)]
141 #[allow(clippy::unknown_clippy_lints)]
142 #[allow(
143 non_camel_case_types,
144 non_snake_case,
145 clippy::extra_unused_type_parameters,
146 clippy::items_after_statements,
147 clippy::no_effect_underscore_binding,
148 clippy::ptr_as_ptr,
149 clippy::ref_as_ptr,
150 clippy::upper_case_acronyms,
151 clippy::use_self,
152 )]
153 #vis #mod_token #ident #expanded
154 }
155}
156
157fn expand_struct(strct: &Struct) -> TokenStream {
158 let ident = &strct.name.rust;
159 let doc = &strct.doc;
160 let attrs = &strct.attrs;
161 let generics = &strct.generics;
162 let type_id = type_id(&strct.name);
163 let fields = strct.fields.iter().map(|field| {
164 let doc = &field.doc;
165 let attrs = &field.attrs;
166 let vis = field.visibility;
169 quote!(#doc #attrs #vis #field)
170 });
171 let mut derives = None;
172 let derived_traits = derive::expand_struct(strct, &mut derives);
173
174 let span = ident.span();
175 let visibility = strct.visibility;
176 let struct_token = strct.struct_token;
177 let struct_def = quote_spanned! {span=>
178 #visibility #struct_token #ident #generics {
179 #(#fields,)*
180 }
181 };
182
183 quote! {
184 #doc
185 #derives
186 #attrs
187 #[repr(C)]
188 #struct_def
189
190 #[automatically_derived]
191 unsafe impl #generics ::cxx::ExternType for #ident #generics {
192 #[allow(unused_attributes)] #[doc(hidden)]
194 type Id = #type_id;
195 type Kind = ::cxx::kind::Trivial;
196 }
197
198 #derived_traits
199 }
200}
201
202fn expand_struct_operators(strct: &Struct) -> TokenStream {
203 let ident = &strct.name.rust;
204 let generics = &strct.generics;
205 let mut operators = TokenStream::new();
206
207 for derive in &strct.derives {
208 let span = derive.span;
209 match derive.what {
210 Trait::PartialEq => {
211 let link_name = mangle::operator(&strct.name, "eq");
212 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
213 let prevent_unwind_label = format!("::{} as PartialEq>::eq", strct.name.rust);
214 operators.extend(quote_spanned! {span=>
215 #[doc(hidden)]
216 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
217 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
218 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
219 ::cxx::private::prevent_unwind(__fn, || *lhs == *rhs)
220 }
221 });
222
223 if !derive::contains(&strct.derives, Trait::Eq) {
224 let link_name = mangle::operator(&strct.name, "ne");
225 let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
226 let prevent_unwind_label = format!("::{} as PartialEq>::ne", strct.name.rust);
227 operators.extend(quote_spanned! {span=>
228 #[doc(hidden)]
229 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
230 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
231 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
232 ::cxx::private::prevent_unwind(__fn, || *lhs != *rhs)
233 }
234 });
235 }
236 }
237 Trait::PartialOrd => {
238 let link_name = mangle::operator(&strct.name, "lt");
239 let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
240 let prevent_unwind_label = format!("::{} as PartialOrd>::lt", strct.name.rust);
241 operators.extend(quote_spanned! {span=>
242 #[doc(hidden)]
243 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
244 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
245 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
246 ::cxx::private::prevent_unwind(__fn, || *lhs < *rhs)
247 }
248 });
249
250 let link_name = mangle::operator(&strct.name, "le");
251 let local_name = format_ident!("__operator_le_{}", strct.name.rust);
252 let prevent_unwind_label = format!("::{} as PartialOrd>::le", strct.name.rust);
253 operators.extend(quote_spanned! {span=>
254 #[doc(hidden)]
255 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
256 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
257 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
258 ::cxx::private::prevent_unwind(__fn, || *lhs <= *rhs)
259 }
260 });
261
262 if !derive::contains(&strct.derives, Trait::Ord) {
263 let link_name = mangle::operator(&strct.name, "gt");
264 let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
265 let prevent_unwind_label = format!("::{} as PartialOrd>::gt", strct.name.rust);
266 operators.extend(quote_spanned! {span=>
267 #[doc(hidden)]
268 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
269 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
270 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
271 ::cxx::private::prevent_unwind(__fn, || *lhs > *rhs)
272 }
273 });
274
275 let link_name = mangle::operator(&strct.name, "ge");
276 let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
277 let prevent_unwind_label = format!("::{} as PartialOrd>::ge", strct.name.rust);
278 operators.extend(quote_spanned! {span=>
279 #[doc(hidden)]
280 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
281 extern "C" fn #local_name #generics(lhs: &#ident #generics, rhs: &#ident #generics) -> bool {
282 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
283 ::cxx::private::prevent_unwind(__fn, || *lhs >= *rhs)
284 }
285 });
286 }
287 }
288 Trait::Hash => {
289 let link_name = mangle::operator(&strct.name, "hash");
290 let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
291 let prevent_unwind_label = format!("::{} as Hash>::hash", strct.name.rust);
292 operators.extend(quote_spanned! {span=>
293 #[doc(hidden)]
294 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
295 #[allow(clippy::cast_possible_truncation)]
296 extern "C" fn #local_name #generics(this: &#ident #generics) -> usize {
297 let __fn = concat!("<", module_path!(), #prevent_unwind_label);
298 ::cxx::private::prevent_unwind(__fn, || ::cxx::private::hash(this))
299 }
300 });
301 }
302 _ => {}
303 }
304 }
305
306 operators
307}
308
309fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
310 let ident = &strct.name.rust;
311 let generics = &strct.generics;
312 let span = ident.span();
313 let impl_token = Token;
314
315 quote_spanned! {span=>
316 #[automatically_derived]
317 #impl_token #generics self::Drop for super::#ident #generics {}
318 }
319}
320
321fn expand_enum(enm: &Enum) -> TokenStream {
322 let ident = &enm.name.rust;
323 let doc = &enm.doc;
324 let attrs = &enm.attrs;
325 let repr = &enm.repr;
326 let type_id = type_id(&enm.name);
327 let variants = enm.variants.iter().map(|variant| {
328 let doc = &variant.doc;
329 let attrs = &variant.attrs;
330 let variant_ident = &variant.name.rust;
331 let discriminant = &variant.discriminant;
332 let span = variant_ident.span();
333 Some(quote_spanned! {span=>
334 #doc
335 #attrs
336 #[allow(dead_code)]
337 pub const #variant_ident: Self = #ident { repr: #discriminant };
338 })
339 });
340 let mut derives = None;
341 let derived_traits = derive::expand_enum(enm, &mut derives);
342
343 let span = ident.span();
344 let visibility = enm.visibility;
345 let struct_token = Token;
346 let enum_repr = quote! {
347 #[allow(missing_docs)]
348 pub repr: #repr,
349 };
350 let enum_def = quote_spanned! {span=>
351 #visibility #struct_token #ident {
352 #enum_repr
353 }
354 };
355
356 quote! {
357 #doc
358 #derives
359 #attrs
360 #[repr(transparent)]
361 #enum_def
362
363 #[automatically_derived]
364 #[allow(non_upper_case_globals)]
365 impl #ident {
366 #(#variants)*
367 }
368
369 #[automatically_derived]
370 unsafe impl ::cxx::ExternType for #ident {
371 #[allow(unused_attributes)] #[doc(hidden)]
373 type Id = #type_id;
374 type Kind = ::cxx::kind::Trivial;
375 }
376
377 #derived_traits
378 }
379}
380
381fn expand_cxx_type(ety: &ExternType) -> TokenStream {
382 let ident = &ety.name.rust;
383 let doc = &ety.doc;
384 let attrs = &ety.attrs;
385 let generics = &ety.generics;
386 let type_id = type_id(&ety.name);
387
388 let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
389 let field = format_ident!("_lifetime_{}", lifetime.ident);
390 quote!(#field: ::cxx::core::marker::PhantomData<&#lifetime ()>)
391 });
392 let repr_fields = quote! {
393 _private: ::cxx::private::Opaque,
394 #(#lifetime_fields,)*
395 };
396
397 let span = ident.span();
398 let visibility = &ety.visibility;
399 let struct_token = Token;
400 let extern_type_def = quote_spanned! {span=>
401 #visibility #struct_token #ident #generics {
402 #repr_fields
403 }
404 };
405
406 quote! {
407 #doc
408 #attrs
409 #[repr(C)]
410 #extern_type_def
411
412 #[automatically_derived]
413 unsafe impl #generics ::cxx::ExternType for #ident #generics {
414 #[allow(unused_attributes)] #[doc(hidden)]
416 type Id = #type_id;
417 type Kind = ::cxx::kind::Opaque;
418 }
419 }
420}
421
422fn expand_cxx_type_assert_pinned(ety: &ExternType, types: &Types) -> TokenStream {
423 let ident = &ety.name.rust;
424 let infer = Token);
425
426 let resolve = types.resolve(ident);
427 let lifetimes = resolve.generics.to_underscore_lifetimes();
428
429 quote! {
430 let _: fn() = {
431 trait __AmbiguousIfImpl<A> {
433 fn infer() {}
434 }
435
436 #[automatically_derived]
437 impl<T> __AmbiguousIfImpl<()> for T
438 where
439 T: ?::cxx::core::marker::Sized
440 {}
441
442 #[allow(dead_code)]
443 struct __Invalid;
444
445 #[automatically_derived]
446 impl<T> __AmbiguousIfImpl<__Invalid> for T
447 where
448 T: ?::cxx::core::marker::Sized + ::cxx::core::marker::Unpin,
449 {}
450
451 <#ident #lifetimes as __AmbiguousIfImpl<#infer>>::infer
456 };
457 }
458}
459
460fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
461 let generics = &efn.generics;
462 let receiver = efn.receiver.iter().map(|receiver| {
463 let receiver_type = receiver.ty();
464 quote!(_: #receiver_type)
465 });
466 let args = efn.args.iter().map(|arg| {
467 let var = &arg.name.rust;
468 let colon = arg.colon_token;
469 let ty = expand_extern_type(&arg.ty, types, true);
470 if arg.ty == RustString {
471 quote!(#var #colon *const #ty)
472 } else if let Type::RustVec(_) = arg.ty {
473 quote!(#var #colon *const #ty)
474 } else if let Type::Fn(_) = arg.ty {
475 quote!(#var #colon ::cxx::private::FatFunction)
476 } else if types.needs_indirect_abi(&arg.ty) {
477 quote!(#var #colon *mut #ty)
478 } else {
479 quote!(#var #colon #ty)
480 }
481 });
482 let all_args = receiver.chain(args);
483 let ret = if efn.throws {
484 quote!(-> ::cxx::private::Result)
485 } else {
486 expand_extern_return_type(&efn.ret, types, true)
487 };
488 let mut outparam = None;
489 if indirect_return(efn, types) {
490 let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
491 outparam = Some(quote!(__return: *mut #ret));
492 }
493 let link_name = mangle::extern_fn(efn, types);
494 let local_name = format_ident!("__{}", efn.name.rust);
495 quote! {
496 #[link_name = #link_name]
497 fn #local_name #generics(#(#all_args,)* #outparam) #ret;
498 }
499}
500
501fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
502 let doc = &efn.doc;
503 let attrs = &efn.attrs;
504 let decl = expand_cxx_function_decl(efn, types);
505 let receiver = efn.receiver.iter().map(|receiver| {
506 let var = receiver.var;
507 if receiver.pinned {
508 let colon = receiver.colon_token;
509 let ty = receiver.ty_self();
510 quote!(#var #colon #ty)
511 } else {
512 let ampersand = receiver.ampersand;
513 let lifetime = &receiver.lifetime;
514 let mutability = receiver.mutability;
515 quote!(#ampersand #lifetime #mutability #var)
516 }
517 });
518 let args = efn.args.iter().map(|arg| quote!(#arg));
519 let all_args = receiver.chain(args);
520 let ret = if efn.throws {
521 let ok = match &efn.ret {
522 Some(ret) => quote!(#ret),
523 None => quote!(()),
524 };
525 quote!(-> ::cxx::core::result::Result<#ok, ::cxx::Exception>)
526 } else {
527 expand_return_type(&efn.ret)
528 };
529 let indirect_return = indirect_return(efn, types);
530 let receiver_var = efn
531 .receiver
532 .iter()
533 .map(|receiver| receiver.var.to_token_stream());
534 let arg_vars = efn.args.iter().map(|arg| {
535 let var = &arg.name.rust;
536 let span = var.span();
537 match &arg.ty {
538 Type::Ident(ident) if ident.rust == RustString => {
539 quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustString)
540 }
541 Type::RustBox(ty) => {
542 if types.is_considered_improper_ctype(&ty.inner) {
543 quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var).cast())
544 } else {
545 quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw(#var))
546 }
547 }
548 Type::UniquePtr(ty) => {
549 if types.is_considered_improper_ctype(&ty.inner) {
550 quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var).cast())
551 } else {
552 quote_spanned!(span=> ::cxx::UniquePtr::into_raw(#var))
553 }
554 }
555 Type::RustVec(_) => quote_spanned!(span=> #var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
556 Type::Ref(ty) => match &ty.inner {
557 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
558 false => quote_spanned!(span=> ::cxx::private::RustString::from_ref(#var)),
559 true => quote_spanned!(span=> ::cxx::private::RustString::from_mut(#var)),
560 },
561 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
562 false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string(#var)),
563 true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string(#var)),
564 },
565 Type::RustVec(_) => match ty.mutable {
566 false => quote_spanned!(span=> ::cxx::private::RustVec::from_ref(#var)),
567 true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)),
568 },
569 inner if types.is_considered_improper_ctype(inner) => {
570 let var = match ty.pinned {
571 false => quote!(#var),
572 true => quote_spanned!(span=> ::cxx::core::pin::Pin::into_inner_unchecked(#var)),
573 };
574 match ty.mutable {
575 false => {
576 quote_spanned!(span=> #var as *const #inner as *const ::cxx::core::ffi::c_void)
577 }
578 true => quote_spanned!(span=> #var as *mut #inner as *mut ::cxx::core::ffi::c_void),
579 }
580 }
581 _ => quote!(#var),
582 },
583 Type::Ptr(ty) => {
584 if types.is_considered_improper_ctype(&ty.inner) {
585 quote_spanned!(span=> #var.cast())
586 } else {
587 quote!(#var)
588 }
589 }
590 Type::Str(_) => quote_spanned!(span=> ::cxx::private::RustStr::from(#var)),
591 Type::SliceRef(ty) => match ty.mutable {
592 false => quote_spanned!(span=> ::cxx::private::RustSlice::from_ref(#var)),
593 true => quote_spanned!(span=> ::cxx::private::RustSlice::from_mut(#var)),
594 },
595 ty if types.needs_indirect_abi(ty) => quote_spanned!(span=> #var.as_mut_ptr()),
596 _ => quote!(#var),
597 }
598 });
599 let vars = receiver_var.chain(arg_vars);
600 let trampolines = efn
601 .args
602 .iter()
603 .filter_map(|arg| {
604 if let Type::Fn(f) = &arg.ty {
605 let var = &arg.name;
606 Some(expand_function_pointer_trampoline(efn, var, f, types))
607 } else {
608 None
609 }
610 })
611 .collect::<TokenStream>();
612 let mut setup = efn
613 .args
614 .iter()
615 .filter(|arg| types.needs_indirect_abi(&arg.ty))
616 .map(|arg| {
617 let var = &arg.name.rust;
618 let span = var.span();
619 quote_spanned! {span=>
622 let mut #var = ::cxx::core::mem::MaybeUninit::new(#var);
623 }
624 })
625 .collect::<TokenStream>();
626 let local_name = format_ident!("__{}", efn.name.rust);
627 let span = efn.semi_token.span;
628 let call = if indirect_return {
629 let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
630 setup.extend(quote_spanned! {span=>
631 let mut __return = ::cxx::core::mem::MaybeUninit::<#ret>::uninit();
632 });
633 setup.extend(if efn.throws {
634 quote_spanned! {span=>
635 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
636 }
637 } else {
638 quote_spanned! {span=>
639 #local_name(#(#vars,)* __return.as_mut_ptr());
640 }
641 });
642 quote_spanned!(span=> __return.assume_init())
643 } else if efn.throws {
644 quote_spanned! {span=>
645 #local_name(#(#vars),*).exception()
646 }
647 } else {
648 quote_spanned! {span=>
649 #local_name(#(#vars),*)
650 }
651 };
652 let mut expr;
653 if efn.throws && efn.sig.ret.is_none() {
654 expr = call;
655 } else {
656 expr = match &efn.ret {
657 None => call,
658 Some(ret) => match ret {
659 Type::Ident(ident) if ident.rust == RustString => {
660 quote_spanned!(span=> #call.into_string())
661 }
662 Type::RustBox(ty) => {
663 if types.is_considered_improper_ctype(&ty.inner) {
664 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call.cast()))
665 } else {
666 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#call))
667 }
668 }
669 Type::RustVec(vec) => {
670 if vec.inner == RustString {
671 quote_spanned!(span=> #call.into_vec_string())
672 } else {
673 quote_spanned!(span=> #call.into_vec())
674 }
675 }
676 Type::UniquePtr(ty) => {
677 if types.is_considered_improper_ctype(&ty.inner) {
678 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call.cast()))
679 } else {
680 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#call))
681 }
682 }
683 Type::Ref(ty) => match &ty.inner {
684 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
685 false => quote_spanned!(span=> #call.as_string()),
686 true => quote_spanned!(span=> #call.as_mut_string()),
687 },
688 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
689 false => quote_spanned!(span=> #call.as_vec_string()),
690 true => quote_spanned!(span=> #call.as_mut_vec_string()),
691 },
692 Type::RustVec(_) => match ty.mutable {
693 false => quote_spanned!(span=> #call.as_vec()),
694 true => quote_spanned!(span=> #call.as_mut_vec()),
695 },
696 inner if types.is_considered_improper_ctype(inner) => {
697 let mutability = ty.mutability;
698 let deref_mut = quote_spanned!(span=> &#mutability *#call.cast());
699 match ty.pinned {
700 false => deref_mut,
701 true => {
702 quote_spanned!(span=> ::cxx::core::pin::Pin::new_unchecked(#deref_mut))
703 }
704 }
705 }
706 _ => call,
707 },
708 Type::Ptr(ty) => {
709 if types.is_considered_improper_ctype(&ty.inner) {
710 quote_spanned!(span=> #call.cast())
711 } else {
712 call
713 }
714 }
715 Type::Str(_) => quote_spanned!(span=> #call.as_str()),
716 Type::SliceRef(slice) => {
717 let inner = &slice.inner;
718 match slice.mutable {
719 false => quote_spanned!(span=> #call.as_slice::<#inner>()),
720 true => quote_spanned!(span=> #call.as_mut_slice::<#inner>()),
721 }
722 }
723 _ => call,
724 },
725 };
726 if efn.throws {
727 expr = quote_spanned!(span=> ::cxx::core::result::Result::Ok(#expr));
728 }
729 }
730 let dispatch = quote_spanned!(span=> unsafe { #setup #expr });
731 let visibility = efn.visibility;
732 let unsafety = &efn.sig.unsafety;
733 let fn_token = efn.sig.fn_token;
734 let ident = &efn.name.rust;
735 let generics = &efn.generics;
736 let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*));
737 let fn_body = quote_spanned!(span=> {
738 #UnsafeExtern extern "C" {
739 #decl
740 }
741 #trampolines
742 #dispatch
743 });
744 match &efn.receiver {
745 None => {
746 quote! {
747 #doc
748 #attrs
749 #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
750 }
751 }
752 Some(receiver) => {
753 let elided_generics;
754 let receiver_ident = &receiver.ty.rust;
755 let resolve = types.resolve(&receiver.ty);
756 let receiver_generics = if receiver.ty.generics.lt_token.is_some() {
757 &receiver.ty.generics
758 } else {
759 elided_generics = Lifetimes {
760 lt_token: resolve.generics.lt_token,
761 lifetimes: resolve
762 .generics
763 .lifetimes
764 .pairs()
765 .map(|pair| {
766 let lifetime = Lifetime::new("'_", pair.value().apostrophe);
767 let punct = pair.punct().map(|&&comma| comma);
768 punctuated::Pair::new(lifetime, punct)
769 })
770 .collect(),
771 gt_token: resolve.generics.gt_token,
772 };
773 &elided_generics
774 };
775 quote_spanned! {ident.span()=>
776 #[automatically_derived]
777 impl #generics #receiver_ident #receiver_generics {
778 #doc
779 #attrs
780 #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
781 }
782 }
783 }
784 }
785}
786
787fn expand_function_pointer_trampoline(
788 efn: &ExternFn,
789 var: &Pair,
790 sig: &Signature,
791 types: &Types,
792) -> TokenStream {
793 let c_trampoline = mangle::c_trampoline(efn, var, types);
794 let r_trampoline = mangle::r_trampoline(efn, var, types);
795 let local_name = parse_quote!(__);
796 let prevent_unwind_label = format!("::{}::{}", efn.name.rust, var.rust);
797 let body_span = efn.semi_token.span;
798 let shim = expand_rust_function_shim_impl(
799 sig,
800 types,
801 &r_trampoline,
802 local_name,
803 prevent_unwind_label,
804 None,
805 Some(&efn.generics),
806 &efn.attrs,
807 body_span,
808 );
809 let var = &var.rust;
810
811 quote! {
812 let #var = ::cxx::private::FatFunction {
813 trampoline: {
814 #UnsafeExtern extern "C" {
815 #[link_name = #c_trampoline]
816 fn trampoline();
817 }
818 #shim
819 trampoline as usize as *const ::cxx::core::ffi::c_void
820 },
821 ptr: #var as usize as *const ::cxx::core::ffi::c_void,
822 };
823 }
824}
825
826fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
827 let ident = &ety.name.rust;
828 let span = ident.span();
829
830 quote_spanned! {span=>
831 use super::#ident;
832 }
833}
834
835fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
836 let ident = &ety.name.rust;
837 let generics = &ety.generics;
838 let span = ident.span();
839 let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
840
841 let mut impls = quote_spanned! {span=>
842 #[automatically_derived]
843 #[doc(hidden)]
844 #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
845 };
846
847 for derive in &ety.derives {
848 if derive.what == Trait::ExternType {
849 let type_id = type_id(&ety.name);
850 let span = derive.span;
851 impls.extend(quote_spanned! {span=>
852 #[automatically_derived]
853 unsafe impl #generics ::cxx::ExternType for #ident #generics {
854 #[allow(unused_attributes)] #[doc(hidden)]
856 type Id = #type_id;
857 type Kind = ::cxx::kind::Opaque;
858 }
859 });
860 }
861 }
862
863 impls
864}
865
866fn expand_rust_type_assert_unpin(ety: &ExternType, types: &Types) -> TokenStream {
867 let ident = &ety.name.rust;
868 let begin_span = Token;
869 let unpin = quote_spanned! {ety.semi_token.span=>
870 #begin_span cxx::core::marker::Unpin
871 };
872
873 let resolve = types.resolve(ident);
874 let lifetimes = resolve.generics.to_underscore_lifetimes();
875
876 quote_spanned! {ident.span()=>
877 let _ = {
878 fn __AssertUnpin<T: ?::cxx::core::marker::Sized + #unpin>() {}
879 __AssertUnpin::<#ident #lifetimes>
880 };
881 }
882}
883
884fn expand_rust_type_layout(ety: &ExternType, types: &Types) -> TokenStream {
885 let ident = &ety.name.rust;
894 let begin_span = Token;
895 let sized = quote_spanned! {ety.semi_token.span=>
896 #begin_span cxx::core::marker::Sized
897 };
898
899 let link_sizeof = mangle::operator(&ety.name, "sizeof");
900 let link_alignof = mangle::operator(&ety.name, "alignof");
901
902 let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
903 let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
904
905 let resolve = types.resolve(ident);
906 let lifetimes = resolve.generics.to_underscore_lifetimes();
907
908 quote_spanned! {ident.span()=>
909 {
910 #[doc(hidden)]
911 #[allow(clippy::needless_maybe_sized)]
912 fn __AssertSized<T: ?#sized + #sized>() -> ::cxx::core::alloc::Layout {
913 ::cxx::core::alloc::Layout::new::<T>()
914 }
915 #[doc(hidden)]
916 #[#UnsafeAttr(#ExportNameAttr = #link_sizeof)]
917 extern "C" fn #local_sizeof() -> usize {
918 __AssertSized::<#ident #lifetimes>().size()
919 }
920 #[doc(hidden)]
921 #[#UnsafeAttr(#ExportNameAttr = #link_alignof)]
922 extern "C" fn #local_alignof() -> usize {
923 __AssertSized::<#ident #lifetimes>().align()
924 }
925 }
926 }
927}
928
929fn expand_forbid(impls: TokenStream) -> TokenStream {
930 quote! {
931 mod forbid {
932 pub trait Drop {}
933 #[automatically_derived]
934 #[allow(drop_bounds)]
935 impl<T: ?::cxx::core::marker::Sized + ::cxx::core::ops::Drop> self::Drop for T {}
936 #impls
937 }
938 }
939}
940
941fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
942 let link_name = mangle::extern_fn(efn, types);
943 let local_name = match &efn.receiver {
944 None => format_ident!("__{}", efn.name.rust),
945 Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust),
946 };
947 let prevent_unwind_label = match &efn.receiver {
948 None => format!("::{}", efn.name.rust),
949 Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust),
950 };
951 let invoke = Some(&efn.name.rust);
952 let body_span = efn.semi_token.span;
953 expand_rust_function_shim_impl(
954 efn,
955 types,
956 &link_name,
957 local_name,
958 prevent_unwind_label,
959 invoke,
960 None,
961 &efn.attrs,
962 body_span,
963 )
964}
965
966fn expand_rust_function_shim_impl(
967 sig: &Signature,
968 types: &Types,
969 link_name: &Symbol,
970 local_name: Ident,
971 prevent_unwind_label: String,
972 invoke: Option<&Ident>,
973 outer_generics: Option<&Generics>,
974 attrs: &OtherAttrs,
975 body_span: Span,
976) -> TokenStream {
977 let generics = outer_generics.unwrap_or(&sig.generics);
978 let receiver_var = sig
979 .receiver
980 .as_ref()
981 .map(|receiver| quote_spanned!(receiver.var.span=> __self));
982 let receiver = sig.receiver.as_ref().map(|receiver| {
983 let colon = receiver.colon_token;
984 let receiver_type = receiver.ty();
985 quote!(#receiver_var #colon #receiver_type)
986 });
987 let args = sig.args.iter().map(|arg| {
988 let var = &arg.name.rust;
989 let colon = arg.colon_token;
990 let ty = expand_extern_type(&arg.ty, types, false);
991 if types.needs_indirect_abi(&arg.ty) {
992 quote!(#var #colon *mut #ty)
993 } else {
994 quote!(#var #colon #ty)
995 }
996 });
997 let all_args = receiver.into_iter().chain(args);
998
999 let mut requires_unsafe = false;
1000 let arg_vars = sig.args.iter().map(|arg| {
1001 let var = &arg.name.rust;
1002 let span = var.span();
1003 match &arg.ty {
1004 Type::Ident(i) if i.rust == RustString => {
1005 requires_unsafe = true;
1006 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_string()))
1007 }
1008 Type::RustBox(_) => {
1009 requires_unsafe = true;
1010 quote_spanned!(span=> ::cxx::alloc::boxed::Box::from_raw(#var))
1011 }
1012 Type::RustVec(vec) => {
1013 requires_unsafe = true;
1014 if vec.inner == RustString {
1015 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec_string()))
1016 } else {
1017 quote_spanned!(span=> ::cxx::core::mem::take((*#var).as_mut_vec()))
1018 }
1019 }
1020 Type::UniquePtr(_) => {
1021 requires_unsafe = true;
1022 quote_spanned!(span=> ::cxx::UniquePtr::from_raw(#var))
1023 }
1024 Type::Ref(ty) => match &ty.inner {
1025 Type::Ident(i) if i.rust == RustString => match ty.mutable {
1026 false => quote_spanned!(span=> #var.as_string()),
1027 true => quote_spanned!(span=> #var.as_mut_string()),
1028 },
1029 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1030 false => quote_spanned!(span=> #var.as_vec_string()),
1031 true => quote_spanned!(span=> #var.as_mut_vec_string()),
1032 },
1033 Type::RustVec(_) => match ty.mutable {
1034 false => quote_spanned!(span=> #var.as_vec()),
1035 true => quote_spanned!(span=> #var.as_mut_vec()),
1036 },
1037 _ => quote!(#var),
1038 },
1039 Type::Str(_) => {
1040 requires_unsafe = true;
1041 quote_spanned!(span=> #var.as_str())
1042 }
1043 Type::SliceRef(slice) => {
1044 requires_unsafe = true;
1045 let inner = &slice.inner;
1046 match slice.mutable {
1047 false => quote_spanned!(span=> #var.as_slice::<#inner>()),
1048 true => quote_spanned!(span=> #var.as_mut_slice::<#inner>()),
1049 }
1050 }
1051 ty if types.needs_indirect_abi(ty) => {
1052 requires_unsafe = true;
1053 quote_spanned!(span=> ::cxx::core::ptr::read(#var))
1054 }
1055 _ => quote!(#var),
1056 }
1057 });
1058 let vars: Vec<_> = receiver_var.into_iter().chain(arg_vars).collect();
1059
1060 let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
1061
1062 let mut requires_closure;
1063 let mut call = match invoke {
1064 Some(_) => {
1065 requires_closure = false;
1066 quote!(#local_name)
1067 }
1068 None => {
1069 requires_closure = true;
1070 requires_unsafe = true;
1071 quote!(::cxx::core::mem::transmute::<*const (), #sig>(__extern))
1072 }
1073 };
1074 requires_closure |= !vars.is_empty();
1075 call.extend(quote! { (#(#vars),*) });
1076
1077 let span = body_span;
1078 let conversion = sig.ret.as_ref().and_then(|ret| match ret {
1079 Type::Ident(ident) if ident.rust == RustString => {
1080 Some(quote_spanned!(span=> ::cxx::private::RustString::from))
1081 }
1082 Type::RustBox(_) => Some(quote_spanned!(span=> ::cxx::alloc::boxed::Box::into_raw)),
1083 Type::RustVec(vec) => {
1084 if vec.inner == RustString {
1085 Some(quote_spanned!(span=> ::cxx::private::RustVec::from_vec_string))
1086 } else {
1087 Some(quote_spanned!(span=> ::cxx::private::RustVec::from))
1088 }
1089 }
1090 Type::UniquePtr(_) => Some(quote_spanned!(span=> ::cxx::UniquePtr::into_raw)),
1091 Type::Ref(ty) => match &ty.inner {
1092 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
1093 false => Some(quote_spanned!(span=> ::cxx::private::RustString::from_ref)),
1094 true => Some(quote_spanned!(span=> ::cxx::private::RustString::from_mut)),
1095 },
1096 Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
1097 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref_vec_string)),
1098 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut_vec_string)),
1099 },
1100 Type::RustVec(_) => match ty.mutable {
1101 false => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_ref)),
1102 true => Some(quote_spanned!(span=> ::cxx::private::RustVec::from_mut)),
1103 },
1104 _ => None,
1105 },
1106 Type::Str(_) => Some(quote_spanned!(span=> ::cxx::private::RustStr::from)),
1107 Type::SliceRef(ty) => match ty.mutable {
1108 false => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_ref)),
1109 true => Some(quote_spanned!(span=> ::cxx::private::RustSlice::from_mut)),
1110 },
1111 _ => None,
1112 });
1113
1114 let mut expr = match conversion {
1115 None => call,
1116 Some(conversion) if !sig.throws => {
1117 requires_closure = true;
1118 quote_spanned!(span=> #conversion(#call))
1119 }
1120 Some(conversion) => {
1121 requires_closure = true;
1122 quote_spanned!(span=> ::cxx::core::result::Result::map(#call, #conversion))
1123 }
1124 };
1125
1126 let mut outparam = None;
1127 let indirect_return = indirect_return(sig, types);
1128 if indirect_return {
1129 let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
1130 outparam = Some(quote_spanned!(span=> __return: *mut #ret,));
1131 }
1132 if sig.throws {
1133 let out = match sig.ret {
1134 Some(_) => quote_spanned!(span=> __return),
1135 None => quote_spanned!(span=> &mut ()),
1136 };
1137 requires_closure = true;
1138 requires_unsafe = true;
1139 expr = quote_spanned!(span=> ::cxx::private::r#try(#out, #expr));
1140 } else if indirect_return {
1141 requires_closure = true;
1142 requires_unsafe = true;
1143 expr = quote_spanned!(span=> ::cxx::core::ptr::write(__return, #expr));
1144 }
1145
1146 if requires_unsafe {
1147 expr = quote_spanned!(span=> unsafe { #expr });
1148 }
1149
1150 let closure = if requires_closure {
1151 quote_spanned!(span=> move || #expr)
1152 } else {
1153 quote!(#local_name)
1154 };
1155
1156 expr = quote_spanned!(span=> ::cxx::private::prevent_unwind(__fn, #closure));
1157
1158 let ret = if sig.throws {
1159 quote!(-> ::cxx::private::Result)
1160 } else {
1161 expand_extern_return_type(&sig.ret, types, false)
1162 };
1163
1164 let pointer = match invoke {
1165 None => Some(quote_spanned!(span=> __extern: *const ())),
1166 Some(_) => None,
1167 };
1168
1169 quote_spanned! {span=>
1170 #attrs
1171 #[doc(hidden)]
1172 #[#UnsafeAttr(#ExportNameAttr = #link_name)]
1173 unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret {
1174 let __fn = ::cxx::private::concat!(::cxx::private::module_path!(), #prevent_unwind_label);
1175 #wrap_super
1176 #expr
1177 }
1178 }
1179}
1180
1181fn expand_rust_function_shim_super(
1184 sig: &Signature,
1185 local_name: &Ident,
1186 invoke: &Ident,
1187) -> TokenStream {
1188 let unsafety = sig.unsafety;
1189 let generics = &sig.generics;
1190
1191 let receiver_var = sig
1192 .receiver
1193 .as_ref()
1194 .map(|receiver| Ident::new("__self", receiver.var.span));
1195 let receiver = sig.receiver.iter().map(|receiver| {
1196 let receiver_type = receiver.ty();
1197 quote!(#receiver_var: #receiver_type)
1198 });
1199 let args = sig.args.iter().map(|arg| quote!(#arg));
1200 let all_args = receiver.chain(args);
1201
1202 let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
1203 let ok = match &sig.ret {
1204 Some(ret) => quote!(#ret),
1205 None => quote!(()),
1206 };
1207 let result_begin = quote_spanned!(result.span=> ::cxx::core::result::Result<#ok, impl);
1210 let result_end = if rustversion::cfg!(since(1.82)) {
1211 quote_spanned!(rangle.span=> ::cxx::core::fmt::Display + use<>>)
1213 } else {
1214 quote_spanned!(rangle.span=> ::cxx::core::fmt::Display>)
1215 };
1216 quote!(-> #result_begin #result_end)
1217 } else {
1218 expand_return_type(&sig.ret)
1219 };
1220
1221 let arg_vars = sig.args.iter().map(|arg| &arg.name.rust);
1222 let vars = receiver_var.iter().chain(arg_vars);
1223
1224 let span = invoke.span();
1225 let call = match &sig.receiver {
1226 None => quote_spanned!(span=> super::#invoke),
1227 Some(receiver) => {
1228 let receiver_type = &receiver.ty.rust;
1229 quote_spanned!(span=> #receiver_type::#invoke)
1230 }
1231 };
1232
1233 let mut body = quote_spanned!(span=> #call(#(#vars,)*));
1234 let mut allow_unused_unsafe = None;
1235 if unsafety.is_some() {
1236 body = quote_spanned!(span=> unsafe { #body });
1237 allow_unused_unsafe = Some(quote_spanned!(span=> #[allow(unused_unsafe)]));
1238 }
1239
1240 quote_spanned! {span=>
1241 #allow_unused_unsafe
1242 #unsafety fn #local_name #generics(#(#all_args,)*) #ret {
1243 #body
1244 }
1245 }
1246}
1247
1248fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
1249 let doc = &alias.doc;
1250 let attrs = &alias.attrs;
1251 let visibility = alias.visibility;
1252 let type_token = alias.type_token;
1253 let ident = &alias.name.rust;
1254 let generics = &alias.generics;
1255 let eq_token = alias.eq_token;
1256 let ty = &alias.ty;
1257 let semi_token = alias.semi_token;
1258
1259 quote! {
1260 #doc
1261 #attrs
1262 #visibility #type_token #ident #generics #eq_token #ty #semi_token
1263 }
1264}
1265
1266fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
1267 let attrs = &alias.attrs;
1268 let ident = &alias.name.rust;
1269 let type_id = type_id(&alias.name);
1270 let begin_span = alias.type_token.span;
1271 let end_span = alias.semi_token.span;
1272 let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
1273 let end = quote_spanned!(end_span=> >);
1274
1275 let mut verify = quote! {
1276 #attrs
1277 const _: fn() = #begin #ident, #type_id #end;
1278 };
1279
1280 if types.required_trivial.contains_key(&alias.name.rust) {
1281 let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
1282 verify.extend(quote! {
1283 #attrs
1284 const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
1285 });
1286 }
1287
1288 verify
1289}
1290
1291fn type_id(name: &Pair) -> TokenStream {
1292 let namespace_segments = name.namespace.iter();
1293 let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
1294 segments.extend(namespace_segments.cloned());
1295 segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
1296 let qualified = QualifiedName { segments };
1297 crate::type_id::expand(Crate::Cxx, qualified)
1298}
1299
1300fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1301 let ident = key.rust;
1302 let resolve = types.resolve(ident);
1303 let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
1304 let link_alloc = format!("{}alloc", link_prefix);
1305 let link_dealloc = format!("{}dealloc", link_prefix);
1306 let link_drop = format!("{}drop", link_prefix);
1307
1308 let local_prefix = format_ident!("{}__box_", ident);
1309 let local_alloc = format_ident!("{}alloc", local_prefix);
1310 let local_dealloc = format_ident!("{}dealloc", local_prefix);
1311 let local_drop = format_ident!("{}drop", local_prefix);
1312
1313 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1314
1315 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1316 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1317 let unsafe_token = format_ident!("unsafe", span = begin_span);
1318 let prevent_unwind_drop_label = format!("::{} as Drop>::drop", ident);
1319
1320 quote_spanned! {end_span=>
1321 #[automatically_derived]
1322 #[doc(hidden)]
1323 #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
1324 #[doc(hidden)]
1325 #[#UnsafeAttr(#ExportNameAttr = #link_alloc)]
1326 unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics> {
1327 ::cxx::alloc::boxed::Box::into_raw(::cxx::alloc::boxed::Box::new(::cxx::core::mem::MaybeUninit::uninit()))
1333 }
1334 #[doc(hidden)]
1335 #[#UnsafeAttr(#ExportNameAttr = #link_dealloc)]
1336 unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::cxx::core::mem::MaybeUninit<#ident #ty_generics>) {
1337 let _ = unsafe { ::cxx::alloc::boxed::Box::from_raw(ptr) };
1339 }
1340 #[doc(hidden)]
1341 #[#UnsafeAttr(#ExportNameAttr = #link_drop)]
1342 unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::alloc::boxed::Box<#ident #ty_generics>) {
1343 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1344 ::cxx::private::prevent_unwind(__fn, || unsafe { ::cxx::core::ptr::drop_in_place(this) });
1345 }
1346 }
1347}
1348
1349fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1350 let elem = key.rust;
1351 let resolve = types.resolve(elem);
1352 let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
1353 let link_new = format!("{}new", link_prefix);
1354 let link_drop = format!("{}drop", link_prefix);
1355 let link_len = format!("{}len", link_prefix);
1356 let link_capacity = format!("{}capacity", link_prefix);
1357 let link_data = format!("{}data", link_prefix);
1358 let link_reserve_total = format!("{}reserve_total", link_prefix);
1359 let link_set_len = format!("{}set_len", link_prefix);
1360 let link_truncate = format!("{}truncate", link_prefix);
1361
1362 let local_prefix = format_ident!("{}__vec_", elem);
1363 let local_new = format_ident!("{}new", local_prefix);
1364 let local_drop = format_ident!("{}drop", local_prefix);
1365 let local_len = format_ident!("{}len", local_prefix);
1366 let local_capacity = format_ident!("{}capacity", local_prefix);
1367 let local_data = format_ident!("{}data", local_prefix);
1368 let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
1369 let local_set_len = format_ident!("{}set_len", local_prefix);
1370 let local_truncate = format_ident!("{}truncate", local_prefix);
1371
1372 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1373
1374 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1375 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1376 let unsafe_token = format_ident!("unsafe", span = begin_span);
1377 let prevent_unwind_drop_label = format!("::{} as Drop>::drop", elem);
1378
1379 quote_spanned! {end_span=>
1380 #[automatically_derived]
1381 #[doc(hidden)]
1382 #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
1383 #[doc(hidden)]
1384 #[#UnsafeAttr(#ExportNameAttr = #link_new)]
1385 unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1386 unsafe {
1388 ::cxx::core::ptr::write(this, ::cxx::private::RustVec::new());
1389 }
1390 }
1391 #[doc(hidden)]
1392 #[#UnsafeAttr(#ExportNameAttr = #link_drop)]
1393 unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
1394 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1395 ::cxx::private::prevent_unwind(
1396 __fn,
1397 || unsafe { ::cxx::core::ptr::drop_in_place(this) },
1398 );
1399 }
1400 #[doc(hidden)]
1401 #[#UnsafeAttr(#ExportNameAttr = #link_len)]
1402 unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1403 unsafe { (*this).len() }
1405 }
1406 #[doc(hidden)]
1407 #[#UnsafeAttr(#ExportNameAttr = #link_capacity)]
1408 unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
1409 unsafe { (*this).capacity() }
1411 }
1412 #[doc(hidden)]
1413 #[#UnsafeAttr(#ExportNameAttr = #link_data)]
1414 unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
1415 unsafe { (*this).as_ptr() }
1417 }
1418 #[doc(hidden)]
1419 #[#UnsafeAttr(#ExportNameAttr = #link_reserve_total)]
1420 unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, new_cap: usize) {
1421 unsafe {
1423 (*this).reserve_total(new_cap);
1424 }
1425 }
1426 #[doc(hidden)]
1427 #[#UnsafeAttr(#ExportNameAttr = #link_set_len)]
1428 unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1429 unsafe {
1431 (*this).set_len(len);
1432 }
1433 }
1434 #[doc(hidden)]
1435 #[#UnsafeAttr(#ExportNameAttr = #link_truncate)]
1436 unsafe extern "C" fn #local_truncate #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
1437 let __fn = concat!("<", module_path!(), #prevent_unwind_drop_label);
1438 ::cxx::private::prevent_unwind(
1439 __fn,
1440 || unsafe { (*this).truncate(len) },
1441 );
1442 }
1443 }
1444}
1445
1446fn expand_unique_ptr(
1447 key: NamedImplKey,
1448 types: &Types,
1449 explicit_impl: Option<&Impl>,
1450) -> TokenStream {
1451 let ident = key.rust;
1452 let name = ident.to_string();
1453 let resolve = types.resolve(ident);
1454 let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
1455 let link_null = format!("{}null", prefix);
1456 let link_uninit = format!("{}uninit", prefix);
1457 let link_raw = format!("{}raw", prefix);
1458 let link_get = format!("{}get", prefix);
1459 let link_release = format!("{}release", prefix);
1460 let link_drop = format!("{}drop", prefix);
1461
1462 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1463
1464 let can_construct_from_value = types.is_maybe_trivial(ident);
1465 let new_method = if can_construct_from_value {
1466 Some(quote! {
1467 fn __new(value: Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1468 #UnsafeExtern extern "C" {
1469 #[link_name = #link_uninit]
1470 fn __uninit(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1471 }
1472 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1473 unsafe {
1474 __uninit(&mut repr).cast::<#ident #ty_generics>().write(value);
1475 }
1476 repr
1477 }
1478 })
1479 } else {
1480 None
1481 };
1482
1483 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1484 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1485 let unsafe_token = format_ident!("unsafe", span = begin_span);
1486
1487 quote_spanned! {end_span=>
1488 #[automatically_derived]
1489 #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
1490 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1491 f.write_str(#name)
1492 }
1493 fn __null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1494 #UnsafeExtern extern "C" {
1495 #[link_name = #link_null]
1496 fn __null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1497 }
1498 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1499 unsafe {
1500 __null(&mut repr);
1501 }
1502 repr
1503 }
1504 #new_method
1505 unsafe fn __raw(raw: *mut Self) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1506 #UnsafeExtern extern "C" {
1507 #[link_name = #link_raw]
1508 fn __raw(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::core::ffi::c_void);
1509 }
1510 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1511 unsafe {
1512 __raw(&mut repr, raw.cast());
1513 }
1514 repr
1515 }
1516 unsafe fn __get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const Self {
1517 #UnsafeExtern extern "C" {
1518 #[link_name = #link_get]
1519 fn __get(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::core::ffi::c_void;
1520 }
1521 unsafe { __get(&repr).cast() }
1522 }
1523 unsafe fn __release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut Self {
1524 #UnsafeExtern extern "C" {
1525 #[link_name = #link_release]
1526 fn __release(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::core::ffi::c_void;
1527 }
1528 unsafe { __release(&mut repr).cast() }
1529 }
1530 unsafe fn __drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
1531 #UnsafeExtern extern "C" {
1532 #[link_name = #link_drop]
1533 fn __drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1534 }
1535 unsafe {
1536 __drop(&mut repr);
1537 }
1538 }
1539 }
1540 }
1541}
1542
1543fn expand_shared_ptr(
1544 key: NamedImplKey,
1545 types: &Types,
1546 explicit_impl: Option<&Impl>,
1547) -> TokenStream {
1548 let ident = key.rust;
1549 let name = ident.to_string();
1550 let resolve = types.resolve(ident);
1551 let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
1552 let link_null = format!("{}null", prefix);
1553 let link_uninit = format!("{}uninit", prefix);
1554 let link_clone = format!("{}clone", prefix);
1555 let link_get = format!("{}get", prefix);
1556 let link_drop = format!("{}drop", prefix);
1557
1558 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1559
1560 let can_construct_from_value = types.is_maybe_trivial(ident);
1561 let new_method = if can_construct_from_value {
1562 Some(quote! {
1563 unsafe fn __new(value: Self, new: *mut ::cxx::core::ffi::c_void) {
1564 #UnsafeExtern extern "C" {
1565 #[link_name = #link_uninit]
1566 fn __uninit(new: *mut ::cxx::core::ffi::c_void) -> *mut ::cxx::core::ffi::c_void;
1567 }
1568 unsafe {
1569 __uninit(new).cast::<#ident #ty_generics>().write(value);
1570 }
1571 }
1572 })
1573 } else {
1574 None
1575 };
1576
1577 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1578 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1579 let unsafe_token = format_ident!("unsafe", span = begin_span);
1580
1581 quote_spanned! {end_span=>
1582 #[automatically_derived]
1583 #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
1584 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1585 f.write_str(#name)
1586 }
1587 unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
1588 #UnsafeExtern extern "C" {
1589 #[link_name = #link_null]
1590 fn __null(new: *mut ::cxx::core::ffi::c_void);
1591 }
1592 unsafe {
1593 __null(new);
1594 }
1595 }
1596 #new_method
1597 unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
1598 #UnsafeExtern extern "C" {
1599 #[link_name = #link_clone]
1600 fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
1601 }
1602 unsafe {
1603 __clone(this, new);
1604 }
1605 }
1606 unsafe fn __get(this: *const ::cxx::core::ffi::c_void) -> *const Self {
1607 #UnsafeExtern extern "C" {
1608 #[link_name = #link_get]
1609 fn __get(this: *const ::cxx::core::ffi::c_void) -> *const ::cxx::core::ffi::c_void;
1610 }
1611 unsafe { __get(this).cast() }
1612 }
1613 unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
1614 #UnsafeExtern extern "C" {
1615 #[link_name = #link_drop]
1616 fn __drop(this: *mut ::cxx::core::ffi::c_void);
1617 }
1618 unsafe {
1619 __drop(this);
1620 }
1621 }
1622 }
1623 }
1624}
1625
1626fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
1627 let ident = key.rust;
1628 let name = ident.to_string();
1629 let resolve = types.resolve(ident);
1630 let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
1631 let link_null = format!("{}null", prefix);
1632 let link_clone = format!("{}clone", prefix);
1633 let link_downgrade = format!("{}downgrade", prefix);
1634 let link_upgrade = format!("{}upgrade", prefix);
1635 let link_drop = format!("{}drop", prefix);
1636
1637 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1638
1639 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1640 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1641 let unsafe_token = format_ident!("unsafe", span = begin_span);
1642
1643 quote_spanned! {end_span=>
1644 #[automatically_derived]
1645 #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
1646 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1647 f.write_str(#name)
1648 }
1649 unsafe fn __null(new: *mut ::cxx::core::ffi::c_void) {
1650 #UnsafeExtern extern "C" {
1651 #[link_name = #link_null]
1652 fn __null(new: *mut ::cxx::core::ffi::c_void);
1653 }
1654 unsafe {
1655 __null(new);
1656 }
1657 }
1658 unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
1659 #UnsafeExtern extern "C" {
1660 #[link_name = #link_clone]
1661 fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void);
1662 }
1663 unsafe {
1664 __clone(this, new);
1665 }
1666 }
1667 unsafe fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void) {
1668 #UnsafeExtern extern "C" {
1669 #[link_name = #link_downgrade]
1670 fn __downgrade(shared: *const ::cxx::core::ffi::c_void, weak: *mut ::cxx::core::ffi::c_void);
1671 }
1672 unsafe {
1673 __downgrade(shared, weak);
1674 }
1675 }
1676 unsafe fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void) {
1677 #UnsafeExtern extern "C" {
1678 #[link_name = #link_upgrade]
1679 fn __upgrade(weak: *const ::cxx::core::ffi::c_void, shared: *mut ::cxx::core::ffi::c_void);
1680 }
1681 unsafe {
1682 __upgrade(weak, shared);
1683 }
1684 }
1685 unsafe fn __drop(this: *mut ::cxx::core::ffi::c_void) {
1686 #UnsafeExtern extern "C" {
1687 #[link_name = #link_drop]
1688 fn __drop(this: *mut ::cxx::core::ffi::c_void);
1689 }
1690 unsafe {
1691 __drop(this);
1692 }
1693 }
1694 }
1695 }
1696}
1697
1698fn expand_cxx_vector(
1699 key: NamedImplKey,
1700 explicit_impl: Option<&Impl>,
1701 types: &Types,
1702) -> TokenStream {
1703 let elem = key.rust;
1704 let name = elem.to_string();
1705 let resolve = types.resolve(elem);
1706 let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
1707 let link_new = format!("{}new", prefix);
1708 let link_size = format!("{}size", prefix);
1709 let link_get_unchecked = format!("{}get_unchecked", prefix);
1710 let link_push_back = format!("{}push_back", prefix);
1711 let link_pop_back = format!("{}pop_back", prefix);
1712 let unique_ptr_prefix = format!(
1713 "cxxbridge1$unique_ptr$std$vector${}$",
1714 resolve.name.to_symbol(),
1715 );
1716 let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
1717 let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
1718 let link_unique_ptr_get = format!("{}get", unique_ptr_prefix);
1719 let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
1720 let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
1721
1722 let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
1723
1724 let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
1725 let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
1726 let unsafe_token = format_ident!("unsafe", span = begin_span);
1727
1728 let can_pass_element_by_value = types.is_maybe_trivial(elem);
1729 let by_value_methods = if can_pass_element_by_value {
1730 Some(quote_spanned! {end_span=>
1731 unsafe fn __push_back(
1732 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
1733 value: &mut ::cxx::core::mem::ManuallyDrop<Self>,
1734 ) {
1735 #UnsafeExtern extern "C" {
1736 #[link_name = #link_push_back]
1737 fn __push_back #impl_generics(
1738 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
1739 value: *mut ::cxx::core::ffi::c_void,
1740 );
1741 }
1742 unsafe {
1743 __push_back(
1744 this,
1745 value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void,
1746 );
1747 }
1748 }
1749 unsafe fn __pop_back(
1750 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
1751 out: &mut ::cxx::core::mem::MaybeUninit<Self>,
1752 ) {
1753 #UnsafeExtern extern "C" {
1754 #[link_name = #link_pop_back]
1755 fn __pop_back #impl_generics(
1756 this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
1757 out: *mut ::cxx::core::ffi::c_void,
1758 );
1759 }
1760 unsafe {
1761 __pop_back(
1762 this,
1763 out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void,
1764 );
1765 }
1766 }
1767 })
1768 } else {
1769 None
1770 };
1771
1772 quote_spanned! {end_span=>
1773 #[automatically_derived]
1774 #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
1775 fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
1776 f.write_str(#name)
1777 }
1778 fn __vector_new() -> *mut ::cxx::CxxVector<Self> {
1779 #UnsafeExtern extern "C" {
1780 #[link_name = #link_new]
1781 fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#elem #ty_generics>;
1782 }
1783 unsafe { __vector_new() }
1784 }
1785 fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
1786 #UnsafeExtern extern "C" {
1787 #[link_name = #link_size]
1788 fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
1789 }
1790 unsafe { __vector_size(v) }
1791 }
1792 unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
1793 #UnsafeExtern extern "C" {
1794 #[link_name = #link_get_unchecked]
1795 fn __get_unchecked #impl_generics(
1796 v: *mut ::cxx::CxxVector<#elem #ty_generics>,
1797 pos: usize,
1798 ) -> *mut ::cxx::core::ffi::c_void;
1799 }
1800 unsafe { __get_unchecked(v, pos) as *mut Self }
1801 }
1802 #by_value_methods
1803 fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1804 #UnsafeExtern extern "C" {
1805 #[link_name = #link_unique_ptr_null]
1806 fn __unique_ptr_null(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1807 }
1808 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1809 unsafe {
1810 __unique_ptr_null(&mut repr);
1811 }
1812 repr
1813 }
1814 unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
1815 #UnsafeExtern extern "C" {
1816 #[link_name = #link_unique_ptr_raw]
1817 fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
1818 }
1819 let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
1820 unsafe {
1821 __unique_ptr_raw(&mut repr, raw);
1822 }
1823 repr
1824 }
1825 unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> {
1826 #UnsafeExtern extern "C" {
1827 #[link_name = #link_unique_ptr_get]
1828 fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>;
1829 }
1830 unsafe { __unique_ptr_get(&repr) }
1831 }
1832 unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> {
1833 #UnsafeExtern extern "C" {
1834 #[link_name = #link_unique_ptr_release]
1835 fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
1836 }
1837 unsafe { __unique_ptr_release(&mut repr) }
1838 }
1839 unsafe fn __unique_ptr_drop(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) {
1840 #UnsafeExtern extern "C" {
1841 #[link_name = #link_unique_ptr_drop]
1842 fn __unique_ptr_drop(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>);
1843 }
1844 unsafe {
1845 __unique_ptr_drop(&mut repr);
1846 }
1847 }
1848 }
1849 }
1850}
1851
1852fn expand_return_type(ret: &Option<Type>) -> TokenStream {
1853 match ret {
1854 Some(ret) => quote!(-> #ret),
1855 None => TokenStream::new(),
1856 }
1857}
1858
1859fn indirect_return(sig: &Signature, types: &Types) -> bool {
1860 sig.ret
1861 .as_ref()
1862 .is_some_and(|ret| sig.throws || types.needs_indirect_abi(ret))
1863}
1864
1865fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
1866 match ty {
1867 Type::Ident(ident) if ident.rust == RustString => {
1868 let span = ident.rust.span();
1869 quote_spanned!(span=> ::cxx::private::RustString)
1870 }
1871 Type::RustBox(ty) | Type::UniquePtr(ty) => {
1872 let span = ty.name.span();
1873 if proper && types.is_considered_improper_ctype(&ty.inner) {
1874 quote_spanned!(span=> *mut ::cxx::core::ffi::c_void)
1875 } else {
1876 let inner = expand_extern_type(&ty.inner, types, proper);
1877 quote_spanned!(span=> *mut #inner)
1878 }
1879 }
1880 Type::RustVec(ty) => {
1881 let span = ty.name.span();
1882 let langle = ty.langle;
1883 let elem = expand_extern_type(&ty.inner, types, proper);
1884 let rangle = ty.rangle;
1885 quote_spanned!(span=> ::cxx::private::RustVec #langle #elem #rangle)
1886 }
1887 Type::Ref(ty) => {
1888 let ampersand = ty.ampersand;
1889 let lifetime = &ty.lifetime;
1890 let mutability = ty.mutability;
1891 match &ty.inner {
1892 Type::Ident(ident) if ident.rust == RustString => {
1893 let span = ident.rust.span();
1894 quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustString)
1895 }
1896 Type::RustVec(ty) => {
1897 let span = ty.name.span();
1898 let langle = ty.langle;
1899 let inner = expand_extern_type(&ty.inner, types, proper);
1900 let rangle = ty.rangle;
1901 quote_spanned!(span=> #ampersand #lifetime #mutability ::cxx::private::RustVec #langle #inner #rangle)
1902 }
1903 inner if proper && types.is_considered_improper_ctype(inner) => {
1904 let star = Token;
1905 match ty.mutable {
1906 false => quote!(#star const ::cxx::core::ffi::c_void),
1907 true => quote!(#star #mutability ::cxx::core::ffi::c_void),
1908 }
1909 }
1910 _ => quote!(#ty),
1911 }
1912 }
1913 Type::Ptr(ty) => {
1914 if proper && types.is_considered_improper_ctype(&ty.inner) {
1915 let star = ty.star;
1916 let mutability = ty.mutability;
1917 let constness = ty.constness;
1918 quote!(#star #mutability #constness ::cxx::core::ffi::c_void)
1919 } else {
1920 quote!(#ty)
1921 }
1922 }
1923 Type::Str(ty) => {
1924 let span = ty.ampersand.span;
1925 let rust_str = Ident::new("RustStr", syn::spanned::Spanned::span(&ty.inner));
1926 quote_spanned!(span=> ::cxx::private::#rust_str)
1927 }
1928 Type::SliceRef(ty) => {
1929 let span = ty.ampersand.span;
1930 let rust_slice = Ident::new("RustSlice", ty.bracket.span.join());
1931 quote_spanned!(span=> ::cxx::private::#rust_slice)
1932 }
1933 _ => quote!(#ty),
1934 }
1935}
1936
1937fn expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream {
1938 let ret = match ret {
1939 Some(ret) if !types.needs_indirect_abi(ret) => ret,
1940 _ => return TokenStream::new(),
1941 };
1942 let ty = expand_extern_type(ret, types, proper);
1943 quote!(-> #ty)
1944}
1945
1946struct UnsafeExtern;
1949
1950impl ToTokens for UnsafeExtern {
1951 fn to_tokens(&self, tokens: &mut TokenStream) {
1952 if rustversion::cfg!(since(1.82)) {
1953 Token).to_tokens(tokens);
1954 }
1955 }
1956}
1957
1958struct UnsafeAttr;
1961struct ExportNameAttr;
1962
1963impl ToTokens for UnsafeAttr {
1964 fn to_tokens(&self, tokens: &mut TokenStream) {
1965 if rustversion::cfg!(since(1.82)) {
1966 Token).to_tokens(tokens);
1967 } else {
1968 Ident::new("cfg_attr", Span::call_site()).to_tokens(tokens);
1969 }
1970 }
1971}
1972
1973impl ToTokens for ExportNameAttr {
1974 fn to_tokens(&self, tokens: &mut TokenStream) {
1975 if rustversion::cfg!(since(1.82)) {
1976 Ident::new("export_name", Span::call_site()).to_tokens(tokens);
1977 } else {
1978 tokens.extend(quote!(all(), export_name));
1979 }
1980 }
1981}