1use crate::gen::block::Block;
2use crate::gen::nested::NamespaceEntries;
3use crate::gen::out::OutFile;
4use crate::gen::{builtin, include, Opt};
5use crate::syntax::atom::Atom::{self, *};
6use crate::syntax::instantiate::{ImplKey, NamedImplKey};
7use crate::syntax::map::UnorderedMap as Map;
8use crate::syntax::primitive::{self, PrimitiveKind};
9use crate::syntax::set::UnorderedSet;
10use crate::syntax::symbol::{self, Symbol};
11use crate::syntax::trivial::{self, TrivialReason};
12use crate::syntax::{
13 derive, mangle, Api, Doc, Enum, EnumRepr, ExternFn, ExternType, Pair, Signature, Struct, Trait,
14 Type, TypeAlias, Types, Var,
15};
16use proc_macro2::Ident;
17
18pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
19 let mut out_file = OutFile::new(header, opt, types);
20 let out = &mut out_file;
21
22 pick_includes_and_builtins(out, apis);
23 out.include.extend(&opt.include);
24
25 write_macros(out, apis);
26 write_forward_declarations(out, apis);
27 write_data_structures(out, apis);
28 write_functions(out, apis);
29 write_generic_instantiations(out);
30
31 builtin::write(out);
32 include::write(out);
33
34 out_file.content()
35}
36
37fn write_macros(out: &mut OutFile, apis: &[Api]) {
38 let mut needs_default_value = false;
39 for api in apis {
40 if let Api::Struct(strct) = api {
41 if !out.types.cxx.contains(&strct.name.rust) {
42 for field in &strct.fields {
43 needs_default_value |= primitive::kind(&field.ty).is_some();
44 }
45 }
46 }
47 }
48
49 if needs_default_value {
50 out.next_section();
51 writeln!(out, "#if __cplusplus >= 201402L");
52 writeln!(out, "#define CXX_DEFAULT_VALUE(value) = value");
53 writeln!(out, "#else");
54 writeln!(out, "#define CXX_DEFAULT_VALUE(value)");
55 writeln!(out, "#endif");
56 }
57}
58
59fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
60 let needs_forward_declaration = |api: &&Api| match api {
61 Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
62 Api::Enum(enm) => !out.types.cxx.contains(&enm.name.rust),
63 _ => false,
64 };
65
66 let apis_by_namespace =
67 NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
68
69 out.next_section();
70 write(out, &apis_by_namespace, 0);
71
72 fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) {
73 let apis = ns_entries.direct_content();
74
75 for api in apis {
76 write!(out, "{:1$}", "", indent);
77 match api {
78 Api::Struct(strct) => write_struct_decl(out, &strct.name),
79 Api::Enum(enm) => write_enum_decl(out, enm),
80 Api::CxxType(ety) => write_struct_using(out, &ety.name),
81 Api::RustType(ety) => write_struct_decl(out, &ety.name),
82 _ => unreachable!(),
83 }
84 }
85
86 for (namespace, nested_ns_entries) in ns_entries.nested_content() {
87 writeln!(out, "{:2$}namespace {} {{", "", namespace, indent);
88 write(out, nested_ns_entries, indent + 2);
89 writeln!(out, "{:1$}}}", "", indent);
90 }
91 }
92}
93
94fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
95 let mut methods_for_type = Map::new();
96 for api in apis {
97 if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
98 if let Some(receiver) = &efn.sig.receiver {
99 methods_for_type
100 .entry(&receiver.ty.rust)
101 .or_insert_with(Vec::new)
102 .push(efn);
103 }
104 }
105 }
106
107 let mut structs_written = UnorderedSet::new();
108 let mut toposorted_structs = out.types.toposorted_structs.iter();
109 for api in apis {
110 match api {
111 Api::Struct(strct) if !structs_written.contains(&strct.name.rust) => {
112 for next in &mut toposorted_structs {
113 if !out.types.cxx.contains(&next.name.rust) {
114 out.next_section();
115 let methods = methods_for_type
116 .get(&next.name.rust)
117 .map(Vec::as_slice)
118 .unwrap_or_default();
119 write_struct(out, next, methods);
120 }
121 structs_written.insert(&next.name.rust);
122 if next.name.rust == strct.name.rust {
123 break;
124 }
125 }
126 }
127 Api::Enum(enm) => {
128 out.next_section();
129 if !out.types.cxx.contains(&enm.name.rust) {
130 write_enum(out, enm);
131 } else if !enm.variants_from_header {
132 check_enum(out, enm);
133 }
134 }
135 Api::RustType(ety) => {
136 out.next_section();
137 let methods = methods_for_type
138 .get(&ety.name.rust)
139 .map(Vec::as_slice)
140 .unwrap_or_default();
141 write_opaque_type(out, ety, methods);
142 }
143 _ => {}
144 }
145 }
146
147 if out.header {
148 return;
149 }
150
151 out.set_namespace(Default::default());
152
153 out.next_section();
154 for api in apis {
155 if let Api::TypeAlias(ety) = api {
156 if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
157 check_trivial_extern_type(out, ety, reasons);
158 }
159 }
160 }
161}
162
163fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
164 if !out.header {
165 for api in apis {
166 match api {
167 Api::Struct(strct) => write_struct_operator_decls(out, strct),
168 Api::RustType(ety) => write_opaque_type_layout_decls(out, ety),
169 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
170 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
171 _ => {}
172 }
173 }
174
175 write_std_specializations(out, apis);
176 }
177
178 for api in apis {
179 match api {
180 Api::Struct(strct) => write_struct_operators(out, strct),
181 Api::RustType(ety) => write_opaque_type_layout(out, ety),
182 Api::RustFunction(efn) => {
183 out.next_section();
184 write_rust_function_shim(out, efn);
185 }
186 _ => {}
187 }
188 }
189}
190
191fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
192 out.set_namespace(Default::default());
193 out.begin_block(Block::Namespace("std"));
194
195 for api in apis {
196 if let Api::Struct(strct) = api {
197 if derive::contains(&strct.derives, Trait::Hash) {
198 out.next_section();
199 out.include.cstddef = true;
200 out.include.functional = true;
201 let qualified = strct.name.to_fully_qualified();
202 writeln!(out, "template <> struct hash<{}> {{", qualified);
203 writeln!(
204 out,
205 " ::std::size_t operator()({} const &self) const noexcept {{",
206 qualified,
207 );
208 let link_name = mangle::operator(&strct.name, "hash");
209 write!(out, " return ::");
210 for name in &strct.name.namespace {
211 write!(out, "{}::", name);
212 }
213 writeln!(out, "{}(self);", link_name);
214 writeln!(out, " }}");
215 writeln!(out, "}};");
216 }
217 }
218 }
219
220 out.end_block(Block::Namespace("std"));
221}
222
223fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
224 for api in apis {
225 if let Api::Include(include) = api {
226 out.include.insert(include);
227 }
228 }
229
230 for ty in out.types {
231 match ty {
232 Type::Ident(ident) => match Atom::from(&ident.rust) {
233 Some(U8 | U16 | U32 | U64 | I8 | I16 | I32 | I64) => out.include.cstdint = true,
234 Some(Usize) => out.include.cstddef = true,
235 Some(Isize) => out.builtin.rust_isize = true,
236 Some(CxxString) => out.include.string = true,
237 Some(RustString) => out.builtin.rust_string = true,
238 Some(Bool | Char | F32 | F64) | None => {}
239 },
240 Type::RustBox(_) => out.builtin.rust_box = true,
241 Type::RustVec(_) => out.builtin.rust_vec = true,
242 Type::UniquePtr(_) => out.include.memory = true,
243 Type::SharedPtr(_) | Type::WeakPtr(_) => out.include.memory = true,
244 Type::Str(_) => out.builtin.rust_str = true,
245 Type::CxxVector(_) => out.include.vector = true,
246 Type::Fn(_) => out.builtin.rust_fn = true,
247 Type::SliceRef(_) => out.builtin.rust_slice = true,
248 Type::Array(_) => out.include.array = true,
249 Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {}
250 }
251 }
252}
253
254fn write_doc(out: &mut OutFile, indent: &str, doc: &Doc) {
255 let mut lines = 0;
256 for line in doc.to_string().lines() {
257 if out.opt.doxygen {
258 writeln!(out, "{}///{}", indent, line);
259 } else {
260 writeln!(out, "{}//{}", indent, line);
261 }
262 lines += 1;
263 }
264 if out.opt.doxygen && lines == 1 {
269 writeln!(out, "{}///", indent);
270 }
271}
272
273fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
274 let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
275 let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd);
276
277 out.set_namespace(&strct.name.namespace);
278 let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
279 writeln!(out, "#ifndef {}", guard);
280 writeln!(out, "#define {}", guard);
281 write_doc(out, "", &strct.doc);
282 writeln!(out, "struct {} final {{", strct.name.cxx);
283
284 for field in &strct.fields {
285 write_doc(out, " ", &field.doc);
286 write!(out, " ");
287 write_type_space(out, &field.ty);
288 write!(out, "{}", field.name.cxx);
289 if let Some(primitive) = primitive::kind(&field.ty) {
290 let default_value = match primitive {
291 PrimitiveKind::Boolean => "false",
292 PrimitiveKind::Number => "0",
293 PrimitiveKind::Pointer => "nullptr",
294 };
295 write!(out, " CXX_DEFAULT_VALUE({})", default_value);
296 }
297 writeln!(out, ";");
298 }
299
300 out.next_section();
301
302 for method in methods {
303 if !method.doc.is_empty() {
304 out.next_section();
305 }
306 write_doc(out, " ", &method.doc);
307 write!(out, " ");
308 let sig = &method.sig;
309 let local_name = method.name.cxx.to_string();
310 let indirect_call = false;
311 write_rust_function_shim_decl(out, &local_name, sig, indirect_call);
312 writeln!(out, ";");
313 if !method.doc.is_empty() {
314 out.next_section();
315 }
316 }
317
318 if operator_eq {
319 writeln!(
320 out,
321 " bool operator==({} const &) const noexcept;",
322 strct.name.cxx,
323 );
324 writeln!(
325 out,
326 " bool operator!=({} const &) const noexcept;",
327 strct.name.cxx,
328 );
329 }
330
331 if operator_ord {
332 writeln!(
333 out,
334 " bool operator<({} const &) const noexcept;",
335 strct.name.cxx,
336 );
337 writeln!(
338 out,
339 " bool operator<=({} const &) const noexcept;",
340 strct.name.cxx,
341 );
342 writeln!(
343 out,
344 " bool operator>({} const &) const noexcept;",
345 strct.name.cxx,
346 );
347 writeln!(
348 out,
349 " bool operator>=({} const &) const noexcept;",
350 strct.name.cxx,
351 );
352 }
353
354 out.include.type_traits = true;
355 writeln!(out, " using IsRelocatable = ::std::true_type;");
356
357 writeln!(out, "}};");
358 writeln!(out, "#endif // {}", guard);
359}
360
361fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
362 writeln!(out, "struct {};", ident.cxx);
363}
364
365fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
366 let repr = match &enm.repr {
367 #[cfg(feature = "experimental-enum-variants-from-header")]
368 EnumRepr::Foreign { .. } => return,
369 EnumRepr::Native { atom, .. } => *atom,
370 };
371 write!(out, "enum class {} : ", enm.name.cxx);
372 write_atom(out, repr);
373 writeln!(out, ";");
374}
375
376fn write_struct_using(out: &mut OutFile, ident: &Pair) {
377 writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
378}
379
380fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[&ExternFn]) {
381 out.set_namespace(&ety.name.namespace);
382 let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol());
383 writeln!(out, "#ifndef {}", guard);
384 writeln!(out, "#define {}", guard);
385 write_doc(out, "", &ety.doc);
386
387 out.builtin.opaque = true;
388 writeln!(
389 out,
390 "struct {} final : public ::rust::Opaque {{",
391 ety.name.cxx,
392 );
393
394 for (i, method) in methods.iter().enumerate() {
395 if i > 0 && !method.doc.is_empty() {
396 out.next_section();
397 }
398 write_doc(out, " ", &method.doc);
399 write!(out, " ");
400 let sig = &method.sig;
401 let local_name = method.name.cxx.to_string();
402 let indirect_call = false;
403 write_rust_function_shim_decl(out, &local_name, sig, indirect_call);
404 writeln!(out, ";");
405 if !method.doc.is_empty() {
406 out.next_section();
407 }
408 }
409
410 writeln!(out, " ~{}() = delete;", ety.name.cxx);
411 writeln!(out);
412
413 out.builtin.layout = true;
414 out.include.cstddef = true;
415 writeln!(out, "private:");
416 writeln!(out, " friend ::rust::layout;");
417 writeln!(out, " struct layout {{");
418 writeln!(out, " static ::std::size_t size() noexcept;");
419 writeln!(out, " static ::std::size_t align() noexcept;");
420 writeln!(out, " }};");
421 writeln!(out, "}};");
422 writeln!(out, "#endif // {}", guard);
423}
424
425fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
426 let repr = match &enm.repr {
427 #[cfg(feature = "experimental-enum-variants-from-header")]
428 EnumRepr::Foreign { .. } => return,
429 EnumRepr::Native { atom, .. } => *atom,
430 };
431 out.set_namespace(&enm.name.namespace);
432 let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol());
433 writeln!(out, "#ifndef {}", guard);
434 writeln!(out, "#define {}", guard);
435 write_doc(out, "", &enm.doc);
436 write!(out, "enum class {} : ", enm.name.cxx);
437 write_atom(out, repr);
438 writeln!(out, " {{");
439 for variant in &enm.variants {
440 write_doc(out, " ", &variant.doc);
441 writeln!(out, " {} = {},", variant.name.cxx, variant.discriminant);
442 }
443 writeln!(out, "}};");
444 writeln!(out, "#endif // {}", guard);
445}
446
447fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
448 let repr = match &enm.repr {
449 #[cfg(feature = "experimental-enum-variants-from-header")]
450 EnumRepr::Foreign { .. } => return,
451 EnumRepr::Native { atom, .. } => *atom,
452 };
453 out.set_namespace(&enm.name.namespace);
454 out.include.type_traits = true;
455 writeln!(
456 out,
457 "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
458 enm.name.cxx,
459 );
460 write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
461 write_atom(out, repr);
462 writeln!(out, "), \"incorrect size\");");
463 for variant in &enm.variants {
464 write!(out, "static_assert(static_cast<");
465 write_atom(out, repr);
466 writeln!(
467 out,
468 ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
469 enm.name.cxx, variant.name.cxx, variant.discriminant,
470 );
471 }
472}
473
474fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[TrivialReason]) {
475 let id = alias.name.to_fully_qualified();
509 out.builtin.relocatable = true;
510 writeln!(out, "static_assert(");
511 if reasons
512 .iter()
513 .all(|r| matches!(r, TrivialReason::StructField(_) | TrivialReason::VecElement))
514 {
515 out.builtin.relocatable_or_array = true;
526 writeln!(out, " ::rust::IsRelocatableOrArray<{}>::value,", id);
527 } else {
528 writeln!(out, " ::rust::IsRelocatable<{}>::value,", id);
529 }
530 writeln!(
531 out,
532 " \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");",
533 id.trim_start_matches("::"),
534 trivial::as_what(&alias.name, reasons),
535 );
536}
537
538fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
539 out.set_namespace(&strct.name.namespace);
540 out.begin_block(Block::ExternC);
541
542 if derive::contains(&strct.derives, Trait::PartialEq) {
543 let link_name = mangle::operator(&strct.name, "eq");
544 writeln!(
545 out,
546 "bool {}({1} const &, {1} const &) noexcept;",
547 link_name, strct.name.cxx,
548 );
549
550 if !derive::contains(&strct.derives, Trait::Eq) {
551 let link_name = mangle::operator(&strct.name, "ne");
552 writeln!(
553 out,
554 "bool {}({1} const &, {1} const &) noexcept;",
555 link_name, strct.name.cxx,
556 );
557 }
558 }
559
560 if derive::contains(&strct.derives, Trait::PartialOrd) {
561 let link_name = mangle::operator(&strct.name, "lt");
562 writeln!(
563 out,
564 "bool {}({1} const &, {1} const &) noexcept;",
565 link_name, strct.name.cxx,
566 );
567
568 let link_name = mangle::operator(&strct.name, "le");
569 writeln!(
570 out,
571 "bool {}({1} const &, {1} const &) noexcept;",
572 link_name, strct.name.cxx,
573 );
574
575 if !derive::contains(&strct.derives, Trait::Ord) {
576 let link_name = mangle::operator(&strct.name, "gt");
577 writeln!(
578 out,
579 "bool {}({1} const &, {1} const &) noexcept;",
580 link_name, strct.name.cxx,
581 );
582
583 let link_name = mangle::operator(&strct.name, "ge");
584 writeln!(
585 out,
586 "bool {}({1} const &, {1} const &) noexcept;",
587 link_name, strct.name.cxx,
588 );
589 }
590 }
591
592 if derive::contains(&strct.derives, Trait::Hash) {
593 out.include.cstddef = true;
594 let link_name = mangle::operator(&strct.name, "hash");
595 writeln!(
596 out,
597 "::std::size_t {}({} const &) noexcept;",
598 link_name, strct.name.cxx,
599 );
600 }
601
602 out.end_block(Block::ExternC);
603}
604
605fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
606 if out.header {
607 return;
608 }
609
610 out.set_namespace(&strct.name.namespace);
611
612 if derive::contains(&strct.derives, Trait::PartialEq) {
613 out.next_section();
614 writeln!(
615 out,
616 "bool {0}::operator==({0} const &rhs) const noexcept {{",
617 strct.name.cxx,
618 );
619 let link_name = mangle::operator(&strct.name, "eq");
620 writeln!(out, " return {}(*this, rhs);", link_name);
621 writeln!(out, "}}");
622
623 out.next_section();
624 writeln!(
625 out,
626 "bool {0}::operator!=({0} const &rhs) const noexcept {{",
627 strct.name.cxx,
628 );
629 if derive::contains(&strct.derives, Trait::Eq) {
630 writeln!(out, " return !(*this == rhs);");
631 } else {
632 let link_name = mangle::operator(&strct.name, "ne");
633 writeln!(out, " return {}(*this, rhs);", link_name);
634 }
635 writeln!(out, "}}");
636 }
637
638 if derive::contains(&strct.derives, Trait::PartialOrd) {
639 out.next_section();
640 writeln!(
641 out,
642 "bool {0}::operator<({0} const &rhs) const noexcept {{",
643 strct.name.cxx,
644 );
645 let link_name = mangle::operator(&strct.name, "lt");
646 writeln!(out, " return {}(*this, rhs);", link_name);
647 writeln!(out, "}}");
648
649 out.next_section();
650 writeln!(
651 out,
652 "bool {0}::operator<=({0} const &rhs) const noexcept {{",
653 strct.name.cxx,
654 );
655 let link_name = mangle::operator(&strct.name, "le");
656 writeln!(out, " return {}(*this, rhs);", link_name);
657 writeln!(out, "}}");
658
659 out.next_section();
660 writeln!(
661 out,
662 "bool {0}::operator>({0} const &rhs) const noexcept {{",
663 strct.name.cxx,
664 );
665 if derive::contains(&strct.derives, Trait::Ord) {
666 writeln!(out, " return !(*this <= rhs);");
667 } else {
668 let link_name = mangle::operator(&strct.name, "gt");
669 writeln!(out, " return {}(*this, rhs);", link_name);
670 }
671 writeln!(out, "}}");
672
673 out.next_section();
674 writeln!(
675 out,
676 "bool {0}::operator>=({0} const &rhs) const noexcept {{",
677 strct.name.cxx,
678 );
679 if derive::contains(&strct.derives, Trait::Ord) {
680 writeln!(out, " return !(*this < rhs);");
681 } else {
682 let link_name = mangle::operator(&strct.name, "ge");
683 writeln!(out, " return {}(*this, rhs);", link_name);
684 }
685 writeln!(out, "}}");
686 }
687}
688
689fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
690 out.set_namespace(&ety.name.namespace);
691 out.begin_block(Block::ExternC);
692
693 let link_name = mangle::operator(&ety.name, "sizeof");
694 writeln!(out, "::std::size_t {}() noexcept;", link_name);
695
696 let link_name = mangle::operator(&ety.name, "alignof");
697 writeln!(out, "::std::size_t {}() noexcept;", link_name);
698
699 out.end_block(Block::ExternC);
700}
701
702fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
703 if out.header {
704 return;
705 }
706
707 out.set_namespace(&ety.name.namespace);
708
709 out.next_section();
710 let link_name = mangle::operator(&ety.name, "sizeof");
711 writeln!(
712 out,
713 "::std::size_t {}::layout::size() noexcept {{",
714 ety.name.cxx,
715 );
716 writeln!(out, " return {}();", link_name);
717 writeln!(out, "}}");
718
719 out.next_section();
720 let link_name = mangle::operator(&ety.name, "alignof");
721 writeln!(
722 out,
723 "::std::size_t {}::layout::align() noexcept {{",
724 ety.name.cxx,
725 );
726 writeln!(out, " return {}();", link_name);
727 writeln!(out, "}}");
728}
729
730fn begin_function_definition(out: &mut OutFile) {
731 if let Some(annotation) = &out.opt.cxx_impl_annotations {
732 write!(out, "{} ", annotation);
733 }
734}
735
736fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
737 out.next_section();
738 out.set_namespace(&efn.name.namespace);
739 out.begin_block(Block::ExternC);
740 begin_function_definition(out);
741 if efn.throws {
742 out.builtin.ptr_len = true;
743 write!(out, "::rust::repr::PtrLen ");
744 } else {
745 write_extern_return_type_space(out, &efn.ret);
746 }
747 let mangled = mangle::extern_fn(efn, out.types);
748 write!(out, "{}(", mangled);
749 if let Some(receiver) = &efn.receiver {
750 write!(
751 out,
752 "{}",
753 out.types.resolve(&receiver.ty).name.to_fully_qualified(),
754 );
755 if !receiver.mutable {
756 write!(out, " const");
757 }
758 write!(out, " &self");
759 }
760 for (i, arg) in efn.args.iter().enumerate() {
761 if i > 0 || efn.receiver.is_some() {
762 write!(out, ", ");
763 }
764 if arg.ty == RustString {
765 write_type_space(out, &arg.ty);
766 write!(out, "const *{}", arg.name.cxx);
767 } else if let Type::RustVec(_) = arg.ty {
768 write_type_space(out, &arg.ty);
769 write!(out, "const *{}", arg.name.cxx);
770 } else {
771 write_extern_arg(out, arg);
772 }
773 }
774 let indirect_return = indirect_return(efn, out.types);
775 if indirect_return {
776 if !efn.args.is_empty() || efn.receiver.is_some() {
777 write!(out, ", ");
778 }
779 write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
780 write!(out, "*return$");
781 }
782 writeln!(out, ") noexcept {{");
783 write!(out, " ");
784 write_return_type(out, &efn.ret);
785 match &efn.receiver {
786 None => write!(out, "(*{}$)(", efn.name.rust),
787 Some(receiver) => write!(
788 out,
789 "({}::*{}$)(",
790 out.types.resolve(&receiver.ty).name.to_fully_qualified(),
791 efn.name.rust,
792 ),
793 }
794 for (i, arg) in efn.args.iter().enumerate() {
795 if i > 0 {
796 write!(out, ", ");
797 }
798 write_type(out, &arg.ty);
799 }
800 write!(out, ")");
801 if let Some(receiver) = &efn.receiver {
802 if !receiver.mutable {
803 write!(out, " const");
804 }
805 }
806 write!(out, " = ");
807 match &efn.receiver {
808 None => write!(out, "{}", efn.name.to_fully_qualified()),
809 Some(receiver) => write!(
810 out,
811 "&{}::{}",
812 out.types.resolve(&receiver.ty).name.to_fully_qualified(),
813 efn.name.cxx,
814 ),
815 }
816 writeln!(out, ";");
817 write!(out, " ");
818 if efn.throws {
819 out.builtin.ptr_len = true;
820 out.builtin.trycatch = true;
821 writeln!(out, "::rust::repr::PtrLen throw$;");
822 writeln!(out, " ::rust::behavior::trycatch(");
823 writeln!(out, " [&] {{");
824 write!(out, " ");
825 }
826 if indirect_return {
827 out.include.new = true;
828 write!(out, "new (return$) ");
829 write_indirect_return_type(out, efn.ret.as_ref().unwrap());
830 write!(out, "(");
831 } else if efn.ret.is_some() {
832 write!(out, "return ");
833 }
834 match &efn.ret {
835 Some(Type::Ref(_)) => write!(out, "&"),
836 Some(Type::Str(_)) if !indirect_return => {
837 out.builtin.rust_str_repr = true;
838 write!(out, "::rust::impl<::rust::Str>::repr(");
839 }
840 Some(ty @ Type::SliceRef(_)) if !indirect_return => {
841 out.builtin.rust_slice_repr = true;
842 write!(out, "::rust::impl<");
843 write_type(out, ty);
844 write!(out, ">::repr(");
845 }
846 _ => {}
847 }
848 match &efn.receiver {
849 None => write!(out, "{}$(", efn.name.rust),
850 Some(_) => write!(out, "(self.*{}$)(", efn.name.rust),
851 }
852 for (i, arg) in efn.args.iter().enumerate() {
853 if i > 0 {
854 write!(out, ", ");
855 }
856 if let Type::RustBox(_) = &arg.ty {
857 write_type(out, &arg.ty);
858 write!(out, "::from_raw({})", arg.name.cxx);
859 } else if let Type::UniquePtr(_) = &arg.ty {
860 write_type(out, &arg.ty);
861 write!(out, "({})", arg.name.cxx);
862 } else if arg.ty == RustString {
863 out.builtin.unsafe_bitcopy = true;
864 write!(
865 out,
866 "::rust::String(::rust::unsafe_bitcopy, *{})",
867 arg.name.cxx,
868 );
869 } else if let Type::RustVec(_) = arg.ty {
870 out.builtin.unsafe_bitcopy = true;
871 write_type(out, &arg.ty);
872 write!(out, "(::rust::unsafe_bitcopy, *{})", arg.name.cxx);
873 } else if out.types.needs_indirect_abi(&arg.ty) {
874 out.include.utility = true;
875 write!(out, "::std::move(*{})", arg.name.cxx);
876 } else {
877 write!(out, "{}", arg.name.cxx);
878 }
879 }
880 write!(out, ")");
881 match &efn.ret {
882 Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
883 Some(Type::UniquePtr(_)) => write!(out, ".release()"),
884 Some(Type::Str(_) | Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
885 _ => {}
886 }
887 if indirect_return {
888 write!(out, ")");
889 }
890 writeln!(out, ";");
891 if efn.throws {
892 writeln!(out, " throw$.ptr = nullptr;");
893 writeln!(out, " }},");
894 writeln!(out, " ::rust::detail::Fail(throw$));");
895 writeln!(out, " return throw$;");
896 }
897 writeln!(out, "}}");
898 for arg in &efn.args {
899 if let Type::Fn(f) = &arg.ty {
900 let var = &arg.name;
901 write_function_pointer_trampoline(out, efn, var, f);
902 }
903 }
904 out.end_block(Block::ExternC);
905}
906
907fn write_function_pointer_trampoline(out: &mut OutFile, efn: &ExternFn, var: &Pair, f: &Signature) {
908 let r_trampoline = mangle::r_trampoline(efn, var, out.types);
909 let indirect_call = true;
910 write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
911
912 out.next_section();
913 let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
914 let doc = Doc::new();
915 write_rust_function_shim_impl(out, &c_trampoline, f, &doc, &r_trampoline, indirect_call);
916}
917
918fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
919 out.set_namespace(&efn.name.namespace);
920 out.begin_block(Block::ExternC);
921 let link_name = mangle::extern_fn(efn, out.types);
922 let indirect_call = false;
923 write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
924 out.end_block(Block::ExternC);
925}
926
927fn write_rust_function_decl_impl(
928 out: &mut OutFile,
929 link_name: &Symbol,
930 sig: &Signature,
931 indirect_call: bool,
932) {
933 out.next_section();
934 if sig.throws {
935 out.builtin.ptr_len = true;
936 write!(out, "::rust::repr::PtrLen ");
937 } else {
938 write_extern_return_type_space(out, &sig.ret);
939 }
940 write!(out, "{}(", link_name);
941 let mut needs_comma = false;
942 if let Some(receiver) = &sig.receiver {
943 write!(
944 out,
945 "{}",
946 out.types.resolve(&receiver.ty).name.to_fully_qualified(),
947 );
948 if !receiver.mutable {
949 write!(out, " const");
950 }
951 write!(out, " &self");
952 needs_comma = true;
953 }
954 for arg in &sig.args {
955 if needs_comma {
956 write!(out, ", ");
957 }
958 write_extern_arg(out, arg);
959 needs_comma = true;
960 }
961 if indirect_return(sig, out.types) {
962 if needs_comma {
963 write!(out, ", ");
964 }
965 match sig.ret.as_ref().unwrap() {
966 Type::Ref(ret) => {
967 write_type_space(out, &ret.inner);
968 if !ret.mutable {
969 write!(out, "const ");
970 }
971 write!(out, "*");
972 }
973 ret => write_type_space(out, ret),
974 }
975 write!(out, "*return$");
976 needs_comma = true;
977 }
978 if indirect_call {
979 if needs_comma {
980 write!(out, ", ");
981 }
982 write!(out, "void *");
983 }
984 writeln!(out, ") noexcept;");
985}
986
987fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
988 out.set_namespace(&efn.name.namespace);
989 let local_name = match &efn.sig.receiver {
990 None => efn.name.cxx.to_string(),
991 Some(receiver) => format!(
992 "{}::{}",
993 out.types.resolve(&receiver.ty).name.cxx,
994 efn.name.cxx,
995 ),
996 };
997 let doc = &efn.doc;
998 let invoke = mangle::extern_fn(efn, out.types);
999 let indirect_call = false;
1000 write_rust_function_shim_impl(out, &local_name, efn, doc, &invoke, indirect_call);
1001}
1002
1003fn write_rust_function_shim_decl(
1004 out: &mut OutFile,
1005 local_name: &str,
1006 sig: &Signature,
1007 indirect_call: bool,
1008) {
1009 begin_function_definition(out);
1010 write_return_type(out, &sig.ret);
1011 write!(out, "{}(", local_name);
1012 for (i, arg) in sig.args.iter().enumerate() {
1013 if i > 0 {
1014 write!(out, ", ");
1015 }
1016 write_type_space(out, &arg.ty);
1017 write!(out, "{}", arg.name.cxx);
1018 }
1019 if indirect_call {
1020 if !sig.args.is_empty() {
1021 write!(out, ", ");
1022 }
1023 write!(out, "void *extern$");
1024 }
1025 write!(out, ")");
1026 if let Some(receiver) = &sig.receiver {
1027 if !receiver.mutable {
1028 write!(out, " const");
1029 }
1030 }
1031 if !sig.throws {
1032 write!(out, " noexcept");
1033 }
1034}
1035
1036fn write_rust_function_shim_impl(
1037 out: &mut OutFile,
1038 local_name: &str,
1039 sig: &Signature,
1040 doc: &Doc,
1041 invoke: &Symbol,
1042 indirect_call: bool,
1043) {
1044 if out.header && sig.receiver.is_some() {
1045 return;
1047 }
1048 if sig.receiver.is_none() {
1049 write_doc(out, "", doc);
1051 }
1052 write_rust_function_shim_decl(out, local_name, sig, indirect_call);
1053 if out.header {
1054 writeln!(out, ";");
1055 return;
1056 }
1057 writeln!(out, " {{");
1058 for arg in &sig.args {
1059 if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
1060 out.include.utility = true;
1061 out.builtin.manually_drop = true;
1062 write!(out, " ::rust::ManuallyDrop<");
1063 write_type(out, &arg.ty);
1064 writeln!(out, "> {}$(::std::move({0}));", arg.name.cxx);
1065 }
1066 }
1067 write!(out, " ");
1068 let indirect_return = indirect_return(sig, out.types);
1069 if indirect_return {
1070 out.builtin.maybe_uninit = true;
1071 write!(out, "::rust::MaybeUninit<");
1072 match sig.ret.as_ref().unwrap() {
1073 Type::Ref(ret) => {
1074 write_type_space(out, &ret.inner);
1075 if !ret.mutable {
1076 write!(out, "const ");
1077 }
1078 write!(out, "*");
1079 }
1080 ret => write_type(out, ret),
1081 }
1082 writeln!(out, "> return$;");
1083 write!(out, " ");
1084 } else if let Some(ret) = &sig.ret {
1085 write!(out, "return ");
1086 match ret {
1087 Type::RustBox(_) => {
1088 write_type(out, ret);
1089 write!(out, "::from_raw(");
1090 }
1091 Type::UniquePtr(_) => {
1092 write_type(out, ret);
1093 write!(out, "(");
1094 }
1095 Type::Ref(_) => write!(out, "*"),
1096 Type::Str(_) => {
1097 out.builtin.rust_str_new_unchecked = true;
1098 write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
1099 }
1100 Type::SliceRef(_) => {
1101 out.builtin.rust_slice_new = true;
1102 write!(out, "::rust::impl<");
1103 write_type(out, ret);
1104 write!(out, ">::slice(");
1105 }
1106 _ => {}
1107 }
1108 }
1109 if sig.throws {
1110 out.builtin.ptr_len = true;
1111 write!(out, "::rust::repr::PtrLen error$ = ");
1112 }
1113 write!(out, "{}(", invoke);
1114 let mut needs_comma = false;
1115 if sig.receiver.is_some() {
1116 write!(out, "*this");
1117 needs_comma = true;
1118 }
1119 for arg in &sig.args {
1120 if needs_comma {
1121 write!(out, ", ");
1122 }
1123 if out.types.needs_indirect_abi(&arg.ty) {
1124 write!(out, "&");
1125 }
1126 write!(out, "{}", arg.name.cxx);
1127 match &arg.ty {
1128 Type::RustBox(_) => write!(out, ".into_raw()"),
1129 Type::UniquePtr(_) => write!(out, ".release()"),
1130 ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
1131 _ => {}
1132 }
1133 needs_comma = true;
1134 }
1135 if indirect_return {
1136 if needs_comma {
1137 write!(out, ", ");
1138 }
1139 write!(out, "&return$.value");
1140 needs_comma = true;
1141 }
1142 if indirect_call {
1143 if needs_comma {
1144 write!(out, ", ");
1145 }
1146 write!(out, "extern$");
1147 }
1148 write!(out, ")");
1149 if !indirect_return {
1150 if let Some(Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_)) =
1151 &sig.ret
1152 {
1153 write!(out, ")");
1154 }
1155 }
1156 writeln!(out, ";");
1157 if sig.throws {
1158 out.builtin.rust_error = true;
1159 writeln!(out, " if (error$.ptr) {{");
1160 writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
1161 writeln!(out, " }}");
1162 }
1163 if indirect_return {
1164 write!(out, " return ");
1165 match sig.ret.as_ref().unwrap() {
1166 Type::Ref(_) => write!(out, "*return$.value"),
1167 _ => {
1168 out.include.utility = true;
1169 write!(out, "::std::move(return$.value)");
1170 }
1171 }
1172 writeln!(out, ";");
1173 }
1174 writeln!(out, "}}");
1175}
1176
1177fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
1178 match ty {
1179 None => write!(out, "void "),
1180 Some(ty) => write_type_space(out, ty),
1181 }
1182}
1183
1184fn indirect_return(sig: &Signature, types: &Types) -> bool {
1185 sig.ret
1186 .as_ref()
1187 .is_some_and(|ret| sig.throws || types.needs_indirect_abi(ret))
1188}
1189
1190fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
1191 match ty {
1192 Type::RustBox(ty) | Type::UniquePtr(ty) => {
1193 write_type_space(out, &ty.inner);
1194 write!(out, "*");
1195 }
1196 Type::Ref(ty) => {
1197 write_type_space(out, &ty.inner);
1198 if !ty.mutable {
1199 write!(out, "const ");
1200 }
1201 write!(out, "*");
1202 }
1203 _ => write_type(out, ty),
1204 }
1205}
1206
1207fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
1208 write_indirect_return_type(out, ty);
1209 match ty {
1210 Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
1211 Type::Str(_) | Type::SliceRef(_) => write!(out, " "),
1212 _ => write_space_after_type(out, ty),
1213 }
1214}
1215
1216fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
1217 match ty {
1218 Some(Type::RustBox(ty) | Type::UniquePtr(ty)) => {
1219 write_type_space(out, &ty.inner);
1220 write!(out, "*");
1221 }
1222 Some(Type::Ref(ty)) => {
1223 write_type_space(out, &ty.inner);
1224 if !ty.mutable {
1225 write!(out, "const ");
1226 }
1227 write!(out, "*");
1228 }
1229 Some(Type::Str(_) | Type::SliceRef(_)) => {
1230 out.builtin.repr_fat = true;
1231 write!(out, "::rust::repr::Fat ");
1232 }
1233 Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
1234 _ => write_return_type(out, ty),
1235 }
1236}
1237
1238fn write_extern_arg(out: &mut OutFile, arg: &Var) {
1239 match &arg.ty {
1240 Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
1241 write_type_space(out, &ty.inner);
1242 write!(out, "*");
1243 }
1244 _ => write_type_space(out, &arg.ty),
1245 }
1246 if out.types.needs_indirect_abi(&arg.ty) {
1247 write!(out, "*");
1248 }
1249 write!(out, "{}", arg.name.cxx);
1250}
1251
1252fn write_type(out: &mut OutFile, ty: &Type) {
1253 match ty {
1254 Type::Ident(ident) => match Atom::from(&ident.rust) {
1255 Some(atom) => write_atom(out, atom),
1256 None => write!(
1257 out,
1258 "{}",
1259 out.types.resolve(ident).name.to_fully_qualified(),
1260 ),
1261 },
1262 Type::RustBox(ty) => {
1263 write!(out, "::rust::Box<");
1264 write_type(out, &ty.inner);
1265 write!(out, ">");
1266 }
1267 Type::RustVec(ty) => {
1268 write!(out, "::rust::Vec<");
1269 write_type(out, &ty.inner);
1270 write!(out, ">");
1271 }
1272 Type::UniquePtr(ptr) => {
1273 write!(out, "::std::unique_ptr<");
1274 write_type(out, &ptr.inner);
1275 write!(out, ">");
1276 }
1277 Type::SharedPtr(ptr) => {
1278 write!(out, "::std::shared_ptr<");
1279 write_type(out, &ptr.inner);
1280 write!(out, ">");
1281 }
1282 Type::WeakPtr(ptr) => {
1283 write!(out, "::std::weak_ptr<");
1284 write_type(out, &ptr.inner);
1285 write!(out, ">");
1286 }
1287 Type::CxxVector(ty) => {
1288 write!(out, "::std::vector<");
1289 write_type(out, &ty.inner);
1290 write!(out, ">");
1291 }
1292 Type::Ref(r) => {
1293 write_type_space(out, &r.inner);
1294 if !r.mutable {
1295 write!(out, "const ");
1296 }
1297 write!(out, "&");
1298 }
1299 Type::Ptr(p) => {
1300 write_type_space(out, &p.inner);
1301 if !p.mutable {
1302 write!(out, "const ");
1303 }
1304 write!(out, "*");
1305 }
1306 Type::Str(_) => {
1307 write!(out, "::rust::Str");
1308 }
1309 Type::SliceRef(slice) => {
1310 write!(out, "::rust::Slice<");
1311 write_type_space(out, &slice.inner);
1312 if slice.mutability.is_none() {
1313 write!(out, "const");
1314 }
1315 write!(out, ">");
1316 }
1317 Type::Fn(f) => {
1318 write!(out, "::rust::Fn<");
1319 match &f.ret {
1320 Some(ret) => write_type(out, ret),
1321 None => write!(out, "void"),
1322 }
1323 write!(out, "(");
1324 for (i, arg) in f.args.iter().enumerate() {
1325 if i > 0 {
1326 write!(out, ", ");
1327 }
1328 write_type(out, &arg.ty);
1329 }
1330 write!(out, ")>");
1331 }
1332 Type::Array(a) => {
1333 write!(out, "::std::array<");
1334 write_type(out, &a.inner);
1335 write!(out, ", {}>", &a.len);
1336 }
1337 Type::Void(_) => unreachable!(),
1338 }
1339}
1340
1341fn write_atom(out: &mut OutFile, atom: Atom) {
1342 match atom {
1343 Bool => write!(out, "bool"),
1344 Char => write!(out, "char"),
1345 U8 => write!(out, "::std::uint8_t"),
1346 U16 => write!(out, "::std::uint16_t"),
1347 U32 => write!(out, "::std::uint32_t"),
1348 U64 => write!(out, "::std::uint64_t"),
1349 Usize => write!(out, "::std::size_t"),
1350 I8 => write!(out, "::std::int8_t"),
1351 I16 => write!(out, "::std::int16_t"),
1352 I32 => write!(out, "::std::int32_t"),
1353 I64 => write!(out, "::std::int64_t"),
1354 Isize => write!(out, "::rust::isize"),
1355 F32 => write!(out, "float"),
1356 F64 => write!(out, "double"),
1357 CxxString => write!(out, "::std::string"),
1358 RustString => write!(out, "::rust::String"),
1359 }
1360}
1361
1362fn write_type_space(out: &mut OutFile, ty: &Type) {
1363 write_type(out, ty);
1364 write_space_after_type(out, ty);
1365}
1366
1367fn write_space_after_type(out: &mut OutFile, ty: &Type) {
1368 match ty {
1369 Type::Ident(_)
1370 | Type::RustBox(_)
1371 | Type::UniquePtr(_)
1372 | Type::SharedPtr(_)
1373 | Type::WeakPtr(_)
1374 | Type::Str(_)
1375 | Type::CxxVector(_)
1376 | Type::RustVec(_)
1377 | Type::SliceRef(_)
1378 | Type::Fn(_)
1379 | Type::Array(_) => write!(out, " "),
1380 Type::Ref(_) | Type::Ptr(_) => {}
1381 Type::Void(_) => unreachable!(),
1382 }
1383}
1384
1385#[derive(Copy, Clone)]
1386enum UniquePtr<'a> {
1387 Ident(&'a Ident),
1388 CxxVector(&'a Ident),
1389}
1390
1391trait ToTypename {
1392 fn to_typename(&self, types: &Types) -> String;
1393}
1394
1395impl ToTypename for Ident {
1396 fn to_typename(&self, types: &Types) -> String {
1397 types.resolve(self).name.to_fully_qualified()
1398 }
1399}
1400
1401impl<'a> ToTypename for UniquePtr<'a> {
1402 fn to_typename(&self, types: &Types) -> String {
1403 match self {
1404 UniquePtr::Ident(ident) => ident.to_typename(types),
1405 UniquePtr::CxxVector(element) => {
1406 format!("::std::vector<{}>", element.to_typename(types))
1407 }
1408 }
1409 }
1410}
1411
1412trait ToMangled {
1413 fn to_mangled(&self, types: &Types) -> Symbol;
1414}
1415
1416impl ToMangled for Ident {
1417 fn to_mangled(&self, types: &Types) -> Symbol {
1418 types.resolve(self).name.to_symbol()
1419 }
1420}
1421
1422impl<'a> ToMangled for UniquePtr<'a> {
1423 fn to_mangled(&self, types: &Types) -> Symbol {
1424 match self {
1425 UniquePtr::Ident(ident) => ident.to_mangled(types),
1426 UniquePtr::CxxVector(element) => {
1427 symbol::join(&[&"std", &"vector", &element.to_mangled(types)])
1428 }
1429 }
1430 }
1431}
1432
1433fn write_generic_instantiations(out: &mut OutFile) {
1434 if out.header {
1435 return;
1436 }
1437
1438 out.next_section();
1439 out.set_namespace(Default::default());
1440 out.begin_block(Block::ExternC);
1441 for impl_key in out.types.impls.keys() {
1442 out.next_section();
1443 match *impl_key {
1444 ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
1445 ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
1446 ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
1447 ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
1448 ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
1449 ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
1450 }
1451 }
1452 out.end_block(Block::ExternC);
1453
1454 out.begin_block(Block::Namespace("rust"));
1455 out.begin_block(Block::InlineNamespace("cxxbridge1"));
1456 for impl_key in out.types.impls.keys() {
1457 match *impl_key {
1458 ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
1459 ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
1460 _ => {}
1461 }
1462 }
1463 out.end_block(Block::InlineNamespace("cxxbridge1"));
1464 out.end_block(Block::Namespace("rust"));
1465}
1466
1467fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) {
1468 let resolve = out.types.resolve(&key);
1469 let inner = resolve.name.to_fully_qualified();
1470 let instance = resolve.name.to_symbol();
1471
1472 writeln!(
1473 out,
1474 "{} *cxxbridge1$box${}$alloc() noexcept;",
1475 inner, instance,
1476 );
1477 writeln!(
1478 out,
1479 "void cxxbridge1$box${}$dealloc({} *) noexcept;",
1480 instance, inner,
1481 );
1482 writeln!(
1483 out,
1484 "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
1485 instance, inner,
1486 );
1487}
1488
1489fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
1490 let element = key.rust;
1491 let inner = element.to_typename(out.types);
1492 let instance = element.to_mangled(out.types);
1493
1494 out.include.cstddef = true;
1495
1496 writeln!(
1497 out,
1498 "void cxxbridge1$rust_vec${}$new(::rust::Vec<{}> const *ptr) noexcept;",
1499 instance, inner,
1500 );
1501 writeln!(
1502 out,
1503 "void cxxbridge1$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
1504 instance, inner,
1505 );
1506 writeln!(
1507 out,
1508 "::std::size_t cxxbridge1$rust_vec${}$len(::rust::Vec<{}> const *ptr) noexcept;",
1509 instance, inner,
1510 );
1511 writeln!(
1512 out,
1513 "::std::size_t cxxbridge1$rust_vec${}$capacity(::rust::Vec<{}> const *ptr) noexcept;",
1514 instance, inner,
1515 );
1516 writeln!(
1517 out,
1518 "{} const *cxxbridge1$rust_vec${}$data(::rust::Vec<{0}> const *ptr) noexcept;",
1519 inner, instance,
1520 );
1521 writeln!(
1522 out,
1523 "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, ::std::size_t new_cap) noexcept;",
1524 instance, inner,
1525 );
1526 writeln!(
1527 out,
1528 "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1529 instance, inner,
1530 );
1531 writeln!(
1532 out,
1533 "void cxxbridge1$rust_vec${}$truncate(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
1534 instance, inner,
1535 );
1536}
1537
1538fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) {
1539 let resolve = out.types.resolve(&key);
1540 let inner = resolve.name.to_fully_qualified();
1541 let instance = resolve.name.to_symbol();
1542
1543 writeln!(out, "template <>");
1544 begin_function_definition(out);
1545 writeln!(
1546 out,
1547 "{} *Box<{}>::allocation::alloc() noexcept {{",
1548 inner, inner,
1549 );
1550 writeln!(out, " return cxxbridge1$box${}$alloc();", instance);
1551 writeln!(out, "}}");
1552
1553 writeln!(out, "template <>");
1554 begin_function_definition(out);
1555 writeln!(
1556 out,
1557 "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
1558 inner, inner,
1559 );
1560 writeln!(out, " cxxbridge1$box${}$dealloc(ptr);", instance);
1561 writeln!(out, "}}");
1562
1563 writeln!(out, "template <>");
1564 begin_function_definition(out);
1565 writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
1566 writeln!(out, " cxxbridge1$box${}$drop(this);", instance);
1567 writeln!(out, "}}");
1568}
1569
1570fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
1571 let element = key.rust;
1572 let inner = element.to_typename(out.types);
1573 let instance = element.to_mangled(out.types);
1574
1575 out.include.cstddef = true;
1576
1577 writeln!(out, "template <>");
1578 begin_function_definition(out);
1579 writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
1580 writeln!(out, " cxxbridge1$rust_vec${}$new(this);", instance);
1581 writeln!(out, "}}");
1582
1583 writeln!(out, "template <>");
1584 begin_function_definition(out);
1585 writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
1586 writeln!(out, " return cxxbridge1$rust_vec${}$drop(this);", instance);
1587 writeln!(out, "}}");
1588
1589 writeln!(out, "template <>");
1590 begin_function_definition(out);
1591 writeln!(
1592 out,
1593 "::std::size_t Vec<{}>::size() const noexcept {{",
1594 inner,
1595 );
1596 writeln!(out, " return cxxbridge1$rust_vec${}$len(this);", instance);
1597 writeln!(out, "}}");
1598
1599 writeln!(out, "template <>");
1600 begin_function_definition(out);
1601 writeln!(
1602 out,
1603 "::std::size_t Vec<{}>::capacity() const noexcept {{",
1604 inner,
1605 );
1606 writeln!(
1607 out,
1608 " return cxxbridge1$rust_vec${}$capacity(this);",
1609 instance,
1610 );
1611 writeln!(out, "}}");
1612
1613 writeln!(out, "template <>");
1614 begin_function_definition(out);
1615 writeln!(out, "{} const *Vec<{0}>::data() const noexcept {{", inner);
1616 writeln!(out, " return cxxbridge1$rust_vec${}$data(this);", instance);
1617 writeln!(out, "}}");
1618
1619 writeln!(out, "template <>");
1620 begin_function_definition(out);
1621 writeln!(
1622 out,
1623 "void Vec<{}>::reserve_total(::std::size_t new_cap) noexcept {{",
1624 inner,
1625 );
1626 writeln!(
1627 out,
1628 " return cxxbridge1$rust_vec${}$reserve_total(this, new_cap);",
1629 instance,
1630 );
1631 writeln!(out, "}}");
1632
1633 writeln!(out, "template <>");
1634 begin_function_definition(out);
1635 writeln!(
1636 out,
1637 "void Vec<{}>::set_len(::std::size_t len) noexcept {{",
1638 inner,
1639 );
1640 writeln!(
1641 out,
1642 " return cxxbridge1$rust_vec${}$set_len(this, len);",
1643 instance,
1644 );
1645 writeln!(out, "}}");
1646
1647 writeln!(out, "template <>");
1648 begin_function_definition(out);
1649 writeln!(out, "void Vec<{}>::truncate(::std::size_t len) {{", inner,);
1650 writeln!(
1651 out,
1652 " return cxxbridge1$rust_vec${}$truncate(this, len);",
1653 instance,
1654 );
1655 writeln!(out, "}}");
1656}
1657
1658fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) {
1659 let ty = UniquePtr::Ident(key.rust);
1660 write_unique_ptr_common(out, ty);
1661}
1662
1663fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
1665 out.include.new = true;
1666 out.include.utility = true;
1667 let inner = ty.to_typename(out.types);
1668 let instance = ty.to_mangled(out.types);
1669
1670 let can_construct_from_value = match ty {
1671 UniquePtr::Ident(ident) => out.types.is_maybe_trivial(ident),
1676 UniquePtr::CxxVector(_) => false,
1677 };
1678
1679 let conditional_delete = match ty {
1680 UniquePtr::Ident(ident) => {
1681 !out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident)
1682 }
1683 UniquePtr::CxxVector(_) => false,
1684 };
1685
1686 if conditional_delete {
1687 out.builtin.is_complete = true;
1688 let definition = match ty {
1689 UniquePtr::Ident(ty) => &out.types.resolve(ty).name.cxx,
1690 UniquePtr::CxxVector(_) => unreachable!(),
1691 };
1692 writeln!(
1693 out,
1694 "static_assert(::rust::detail::is_complete<{}>::value, \"definition of {} is required\");",
1695 inner, definition,
1696 );
1697 }
1698 writeln!(
1699 out,
1700 "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
1701 inner,
1702 );
1703 writeln!(
1704 out,
1705 "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
1706 inner,
1707 );
1708
1709 begin_function_definition(out);
1710 writeln!(
1711 out,
1712 "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
1713 instance, inner,
1714 );
1715 writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>();", inner);
1716 writeln!(out, "}}");
1717
1718 if can_construct_from_value {
1719 out.builtin.maybe_uninit = true;
1720 begin_function_definition(out);
1721 writeln!(
1722 out,
1723 "{} *cxxbridge1$unique_ptr${}$uninit(::std::unique_ptr<{}> *ptr) noexcept {{",
1724 inner, instance, inner,
1725 );
1726 writeln!(
1727 out,
1728 " {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
1729 inner, inner, inner,
1730 );
1731 writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
1732 writeln!(out, " return uninit;");
1733 writeln!(out, "}}");
1734 }
1735
1736 begin_function_definition(out);
1737 writeln!(
1738 out,
1739 "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
1740 instance, inner, inner,
1741 );
1742 writeln!(out, " ::new (ptr) ::std::unique_ptr<{}>(raw);", inner);
1743 writeln!(out, "}}");
1744
1745 begin_function_definition(out);
1746 writeln!(
1747 out,
1748 "{} const *cxxbridge1$unique_ptr${}$get(::std::unique_ptr<{}> const &ptr) noexcept {{",
1749 inner, instance, inner,
1750 );
1751 writeln!(out, " return ptr.get();");
1752 writeln!(out, "}}");
1753
1754 begin_function_definition(out);
1755 writeln!(
1756 out,
1757 "{} *cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}> &ptr) noexcept {{",
1758 inner, instance, inner,
1759 );
1760 writeln!(out, " return ptr.release();");
1761 writeln!(out, "}}");
1762
1763 begin_function_definition(out);
1764 writeln!(
1765 out,
1766 "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
1767 instance, inner,
1768 );
1769 if conditional_delete {
1770 out.builtin.deleter_if = true;
1771 writeln!(
1772 out,
1773 " ::rust::deleter_if<::rust::detail::is_complete<{}>::value>{{}}(ptr);",
1774 inner,
1775 );
1776 } else {
1777 writeln!(out, " ptr->~unique_ptr();");
1778 }
1779 writeln!(out, "}}");
1780}
1781
1782fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) {
1783 let ident = key.rust;
1784 let resolve = out.types.resolve(ident);
1785 let inner = resolve.name.to_fully_qualified();
1786 let instance = resolve.name.to_symbol();
1787
1788 out.include.new = true;
1789 out.include.utility = true;
1790
1791 let can_construct_from_value = out.types.is_maybe_trivial(ident);
1796
1797 writeln!(
1798 out,
1799 "static_assert(sizeof(::std::shared_ptr<{}>) == 2 * sizeof(void *), \"\");",
1800 inner,
1801 );
1802 writeln!(
1803 out,
1804 "static_assert(alignof(::std::shared_ptr<{}>) == alignof(void *), \"\");",
1805 inner,
1806 );
1807
1808 begin_function_definition(out);
1809 writeln!(
1810 out,
1811 "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
1812 instance, inner,
1813 );
1814 writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>();", inner);
1815 writeln!(out, "}}");
1816
1817 if can_construct_from_value {
1818 out.builtin.maybe_uninit = true;
1819 begin_function_definition(out);
1820 writeln!(
1821 out,
1822 "{} *cxxbridge1$shared_ptr${}$uninit(::std::shared_ptr<{}> *ptr) noexcept {{",
1823 inner, instance, inner,
1824 );
1825 writeln!(
1826 out,
1827 " {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
1828 inner, inner, inner,
1829 );
1830 writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
1831 writeln!(out, " return uninit;");
1832 writeln!(out, "}}");
1833 }
1834
1835 begin_function_definition(out);
1836 writeln!(
1837 out,
1838 "void cxxbridge1$shared_ptr${}$clone(::std::shared_ptr<{}> const &self, ::std::shared_ptr<{}> *ptr) noexcept {{",
1839 instance, inner, inner,
1840 );
1841 writeln!(out, " ::new (ptr) ::std::shared_ptr<{}>(self);", inner);
1842 writeln!(out, "}}");
1843
1844 begin_function_definition(out);
1845 writeln!(
1846 out,
1847 "{} const *cxxbridge1$shared_ptr${}$get(::std::shared_ptr<{}> const &self) noexcept {{",
1848 inner, instance, inner,
1849 );
1850 writeln!(out, " return self.get();");
1851 writeln!(out, "}}");
1852
1853 begin_function_definition(out);
1854 writeln!(
1855 out,
1856 "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{",
1857 instance, inner,
1858 );
1859 writeln!(out, " self->~shared_ptr();");
1860 writeln!(out, "}}");
1861}
1862
1863fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) {
1864 let resolve = out.types.resolve(&key);
1865 let inner = resolve.name.to_fully_qualified();
1866 let instance = resolve.name.to_symbol();
1867
1868 out.include.new = true;
1869 out.include.utility = true;
1870
1871 writeln!(
1872 out,
1873 "static_assert(sizeof(::std::weak_ptr<{}>) == 2 * sizeof(void *), \"\");",
1874 inner,
1875 );
1876 writeln!(
1877 out,
1878 "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");",
1879 inner,
1880 );
1881
1882 begin_function_definition(out);
1883 writeln!(
1884 out,
1885 "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{",
1886 instance, inner,
1887 );
1888 writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>();", inner);
1889 writeln!(out, "}}");
1890
1891 begin_function_definition(out);
1892 writeln!(
1893 out,
1894 "void cxxbridge1$weak_ptr${}$clone(::std::weak_ptr<{}> const &self, ::std::weak_ptr<{}> *ptr) noexcept {{",
1895 instance, inner, inner,
1896 );
1897 writeln!(out, " ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
1898 writeln!(out, "}}");
1899
1900 begin_function_definition(out);
1901 writeln!(
1902 out,
1903 "void cxxbridge1$weak_ptr${}$downgrade(::std::shared_ptr<{}> const &shared, ::std::weak_ptr<{}> *weak) noexcept {{",
1904 instance, inner, inner,
1905 );
1906 writeln!(out, " ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
1907 writeln!(out, "}}");
1908
1909 begin_function_definition(out);
1910 writeln!(
1911 out,
1912 "void cxxbridge1$weak_ptr${}$upgrade(::std::weak_ptr<{}> const &weak, ::std::shared_ptr<{}> *shared) noexcept {{",
1913 instance, inner, inner,
1914 );
1915 writeln!(
1916 out,
1917 " ::new (shared) ::std::shared_ptr<{}>(weak.lock());",
1918 inner,
1919 );
1920 writeln!(out, "}}");
1921
1922 begin_function_definition(out);
1923 writeln!(
1924 out,
1925 "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
1926 instance, inner,
1927 );
1928 writeln!(out, " self->~weak_ptr();");
1929 writeln!(out, "}}");
1930}
1931
1932fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
1933 let element = key.rust;
1934 let inner = element.to_typename(out.types);
1935 let instance = element.to_mangled(out.types);
1936
1937 out.include.cstddef = true;
1938 out.include.utility = true;
1939 out.builtin.destroy = true;
1940
1941 begin_function_definition(out);
1942 writeln!(
1943 out,
1944 "::std::vector<{}> *cxxbridge1$std$vector${}$new() noexcept {{",
1945 inner, instance,
1946 );
1947 writeln!(out, " return new ::std::vector<{}>();", inner);
1948 writeln!(out, "}}");
1949
1950 begin_function_definition(out);
1951 writeln!(
1952 out,
1953 "::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{",
1954 instance, inner,
1955 );
1956 writeln!(out, " return s.size();");
1957 writeln!(out, "}}");
1958
1959 begin_function_definition(out);
1960 writeln!(
1961 out,
1962 "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
1963 inner, instance, inner,
1964 );
1965 writeln!(out, " return &(*s)[pos];");
1966 writeln!(out, "}}");
1967
1968 if out.types.is_maybe_trivial(element) {
1969 begin_function_definition(out);
1970 writeln!(
1971 out,
1972 "void cxxbridge1$std$vector${}$push_back(::std::vector<{}> *v, {} *value) noexcept {{",
1973 instance, inner, inner,
1974 );
1975 writeln!(out, " v->push_back(::std::move(*value));");
1976 writeln!(out, " ::rust::destroy(value);");
1977 writeln!(out, "}}");
1978
1979 begin_function_definition(out);
1980 writeln!(
1981 out,
1982 "void cxxbridge1$std$vector${}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{",
1983 instance, inner, inner,
1984 );
1985 writeln!(out, " ::new (out) {}(::std::move(v->back()));", inner);
1986 writeln!(out, " v->pop_back();");
1987 writeln!(out, "}}");
1988 }
1989
1990 out.include.memory = true;
1991 write_unique_ptr_common(out, UniquePtr::CxxVector(element));
1992}