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