blob: fc093e7ceb15fb177b0c8307ad0fe3c5db956155 [file] [log] [blame]
Adrian Taylor565ddf02020-10-29 21:12:36 -07001use crate::gen::namespace_organizer::NamespaceEntries;
David Tolnay8810a542020-10-31 21:39:22 -07002use crate::gen::out::OutFile;
David Tolnay2f3e90b2020-10-31 22:16:51 -07003use crate::gen::{ifndef, include, Opt};
David Tolnay7db73692019-10-20 14:51:12 -04004use crate::syntax::atom::Atom::{self, *};
David Tolnay891061b2020-04-19 22:42:33 -07005use crate::syntax::symbol::Symbol;
Adrian Taylorc8713432020-10-21 18:20:55 -07006use crate::syntax::{
David Tolnay2f3e90b2020-10-31 22:16:51 -07007 mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
8 Types, Var,
Adrian Taylorc8713432020-10-21 18:20:55 -07009};
David Tolnay7db73692019-10-20 14:51:12 -040010use proc_macro2::Ident;
Joel Galenson0f654ff2020-05-04 20:04:21 -070011use std::collections::HashMap;
David Tolnay7db73692019-10-20 14:51:12 -040012
David Tolnayb560a0f2020-10-30 21:28:45 -070013pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -> OutFile<'a> {
14 let mut out_file = OutFile::new(header, types);
David Tolnay7db73692019-10-20 14:51:12 -040015 let out = &mut out_file;
16
David Tolnay54702b92020-07-31 11:50:09 -070017 if header {
David Tolnay8810a542020-10-31 21:39:22 -070018 writeln!(out.include, "#pragma once");
David Tolnay54702b92020-07-31 11:50:09 -070019 }
20
David Tolnaye629c642020-10-31 22:02:09 -070021 pick_includes_and_builtins(out, apis);
David Tolnay4aae7c02020-10-28 12:35:42 -070022 out.include.extend(&opt.include);
David Tolnay7db73692019-10-20 14:51:12 -040023
Adrian Taylor565ddf02020-10-29 21:12:36 -070024 let apis_by_namespace = NamespaceEntries::new(apis);
Adrian Taylorc8713432020-10-21 18:20:55 -070025
David Tolnay04b81652020-10-31 22:43:25 -070026 gen_namespace_forward_declarations(out, &apis_by_namespace);
27 gen_namespace_contents(out, &apis_by_namespace, opt);
Adrian Taylorc8713432020-10-21 18:20:55 -070028
29 if !header {
30 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -070031 write_generic_instantiations(out);
David Tolnay7db73692019-10-20 14:51:12 -040032 }
33
David Tolnaye629c642020-10-31 22:02:09 -070034 write_builtins(out);
David Tolnay2f3e90b2020-10-31 22:16:51 -070035 include::write(out);
Adrian Taylorc8713432020-10-21 18:20:55 -070036
37 out_file
38}
39
David Tolnay04b81652020-10-31 22:43:25 -070040fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
Adrian Taylor565ddf02020-10-29 21:12:36 -070041 let apis = ns_entries.entries();
Adrian Taylorc8713432020-10-21 18:20:55 -070042
David Tolnay7db73692019-10-20 14:51:12 -040043 out.next_section();
David Tolnay630af882020-10-31 22:03:47 -070044 for api in apis {
David Tolnay7db73692019-10-20 14:51:12 -040045 match api {
David Tolnay880d1f82020-10-31 22:05:24 -070046 Api::Include(include) => out.include.insert(include),
Adrian Taylorc8713432020-10-21 18:20:55 -070047 Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
48 Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
49 Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
David Tolnay7c295462020-04-25 12:45:07 -070050 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -040051 }
52 }
53
Adrian Taylorf9213622020-10-31 22:25:42 -070054 out.next_section();
55
56 for (child_ns, child_ns_entries) in ns_entries.children() {
57 writeln!(out, "namespace {} {{", child_ns);
David Tolnayef0473a2020-10-31 22:44:52 -070058 gen_namespace_forward_declarations(out, child_ns_entries);
Adrian Taylorf9213622020-10-31 22:25:42 -070059 writeln!(out, "}} // namespace {}", child_ns);
60 }
61}
62
David Tolnay04b81652020-10-31 22:43:25 -070063fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt: &Opt) {
Adrian Taylorf9213622020-10-31 22:25:42 -070064 let apis = ns_entries.entries();
65
David Tolnayf94bef12020-04-17 14:46:42 -070066 let mut methods_for_type = HashMap::new();
David Tolnay630af882020-10-31 22:03:47 -070067 for api in apis {
David Tolnayf94bef12020-04-17 14:46:42 -070068 if let Api::RustFunction(efn) = api {
69 if let Some(receiver) = &efn.sig.receiver {
70 methods_for_type
Adrian Taylorc8713432020-10-21 18:20:55 -070071 .entry(&receiver.ty.rust)
David Tolnayf94bef12020-04-17 14:46:42 -070072 .or_insert_with(Vec::new)
73 .push(efn);
74 }
75 }
76 }
Joel Galenson968738f2020-04-15 14:19:33 -070077
David Tolnay7db73692019-10-20 14:51:12 -040078 for api in apis {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070079 match api {
80 Api::Struct(strct) => {
81 out.next_section();
David Tolnay4d148422020-10-31 22:41:37 -070082 if !out.types.cxx.contains(&strct.ident.rust) {
David Tolnaya7c2ea12020-10-30 21:32:53 -070083 write_struct(out, strct);
David Tolnaya593d6e2020-08-29 19:48:08 -070084 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070085 }
Joel Galensonc03402a2020-04-23 17:31:09 -070086 Api::Enum(enm) => {
87 out.next_section();
David Tolnay4d148422020-10-31 22:41:37 -070088 if out.types.cxx.contains(&enm.ident.rust) {
Joel Galenson905eb2e2020-05-04 14:58:14 -070089 check_enum(out, enm);
90 } else {
91 write_enum(out, enm);
92 }
Joel Galensonc03402a2020-04-23 17:31:09 -070093 }
David Tolnayc1fe0052020-04-17 15:15:06 -070094 Api::RustType(ety) => {
Adrian Taylorc8713432020-10-21 18:20:55 -070095 if let Some(methods) = methods_for_type.get(&ety.ident.rust) {
David Tolnay46a54e72020-04-17 14:48:21 -070096 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -070097 write_struct_with_methods(out, ety, methods);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070098 }
David Tolnayc1fe0052020-04-17 15:15:06 -070099 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700100 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400101 }
102 }
103
David Tolnayfabca772020-10-03 21:25:41 -0700104 out.next_section();
105 for api in apis {
106 if let Api::TypeAlias(ety) = api {
David Tolnay4d148422020-10-31 22:41:37 -0700107 if out.types.required_trivial.contains_key(&ety.ident.rust) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700108 check_trivial_extern_type(out, &ety.ident.cxx)
David Tolnayfabca772020-10-03 21:25:41 -0700109 }
110 }
111 }
112
David Tolnayce5a91f2020-10-31 22:42:08 -0700113 if !out.header {
David Tolnay7db73692019-10-20 14:51:12 -0400114 out.begin_block("extern \"C\"");
David Tolnayebef4a22020-03-17 15:33:47 -0700115 write_exception_glue(out, apis);
David Tolnay7db73692019-10-20 14:51:12 -0400116 for api in apis {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700117 let (efn, write): (_, fn(_, _, _)) = match api {
David Tolnay7db73692019-10-20 14:51:12 -0400118 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
119 Api::RustFunction(efn) => (efn, write_rust_function_decl),
120 _ => continue,
121 };
122 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700123 write(out, efn, &opt.cxx_impl_annotations);
David Tolnay7db73692019-10-20 14:51:12 -0400124 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800125 out.end_block("extern \"C\"");
David Tolnay7db73692019-10-20 14:51:12 -0400126 }
127
128 for api in apis {
129 if let Api::RustFunction(efn) = api {
130 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700131 write_rust_function_shim(out, efn);
David Tolnay7db73692019-10-20 14:51:12 -0400132 }
133 }
134
135 out.next_section();
Adrian Taylorc8713432020-10-21 18:20:55 -0700136
Adrian Taylor565ddf02020-10-29 21:12:36 -0700137 for (child_ns, child_ns_entries) in ns_entries.children() {
Adrian Taylorc8713432020-10-21 18:20:55 -0700138 writeln!(out, "namespace {} {{", child_ns);
David Tolnayef0473a2020-10-31 22:44:52 -0700139 gen_namespace_contents(out, child_ns_entries, opt);
Adrian Taylorc8713432020-10-21 18:20:55 -0700140 writeln!(out, "}} // namespace {}", child_ns);
David Tolnay7db73692019-10-20 14:51:12 -0400141 }
David Tolnay7db73692019-10-20 14:51:12 -0400142}
143
David Tolnay528200f2020-10-31 21:02:22 -0700144fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700145 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -0400146 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700147 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnay89e386d2020-10-03 19:02:19 -0700148 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
149 | Some(I64) => out.include.cstdint = true,
150 Some(Usize) => out.include.cstddef = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700151 Some(Isize) => {
152 out.include.basetsd = true;
153 out.builtin.rust_isize = true;
154 }
David Tolnay89e386d2020-10-03 19:02:19 -0700155 Some(CxxString) => out.include.string = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700156 Some(RustString) => {
157 out.include.array = true;
158 out.include.cstdint = true;
159 out.include.string = true;
160 out.builtin.rust_string = true;
161 }
162 Some(Bool) | Some(F32) | Some(F64) | None => {}
David Tolnay89e386d2020-10-03 19:02:19 -0700163 },
David Tolnayb7a7cb62020-03-17 21:18:40 -0700164 Type::RustBox(_) => {
David Tolnay0ecd05a2020-07-29 16:32:03 -0700165 out.include.new = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700166 out.include.type_traits = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700167 out.builtin.rust_box = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700168 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700169 Type::RustVec(_) => {
David Tolnay9c6bf2d2020-04-24 15:27:07 -0700170 out.include.array = true;
David Tolnay0ecd05a2020-07-29 16:32:03 -0700171 out.include.new = true;
David Tolnayc87c2152020-04-24 17:07:41 -0700172 out.include.type_traits = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700173 out.builtin.panic = true;
174 out.builtin.rust_vec = true;
175 out.builtin.unsafe_bitcopy = true;
Myron Ahneba35cf2020-02-05 19:41:51 +0700176 }
David Tolnayb9da1462020-10-31 21:03:41 -0700177 Type::UniquePtr(_) => out.include.memory = true,
David Tolnayb7a7cb62020-03-17 21:18:40 -0700178 Type::Str(_) => {
179 out.include.cstdint = true;
180 out.include.string = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700181 out.builtin.rust_str = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700182 }
David Tolnayb9da1462020-10-31 21:03:41 -0700183 Type::CxxVector(_) => out.include.vector = true,
David Tolnay75dca2e2020-03-25 20:17:52 -0700184 Type::Fn(_) => {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700185 out.builtin.rust_fn = true;
David Tolnay75dca2e2020-03-25 20:17:52 -0700186 }
David Tolnayb9da1462020-10-31 21:03:41 -0700187 Type::Slice(_) => {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700188 out.builtin.rust_slice = true;
David Tolnay4770b472020-04-14 16:32:59 -0700189 }
David Tolnayb9da1462020-10-31 21:03:41 -0700190 Type::SliceRefU8(_) => {
David Tolnayb7a7cb62020-03-17 21:18:40 -0700191 out.include.cstdint = true;
David Tolnayb9da1462020-10-31 21:03:41 -0700192 out.builtin.rust_slice = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700193 }
194 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400195 }
196 }
197
David Tolnay09011c32020-03-06 14:40:28 -0800198 for api in apis {
David Tolnayb7a7cb62020-03-17 21:18:40 -0700199 match api {
200 Api::CxxFunction(efn) if !out.header => {
David Tolnay5d121442020-03-17 22:14:40 -0700201 if efn.throws {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700202 out.builtin.trycatch = true;
David Tolnaya4eb9432020-10-31 20:32:19 -0700203 } else if let Some(Type::Str(_)) = efn.ret {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700204 out.builtin.rust_str_repr = true;
David Tolnay5d121442020-03-17 22:14:40 -0700205 }
David Tolnayb7a7cb62020-03-17 21:18:40 -0700206 for arg in &efn.args {
David Tolnaya4eb9432020-10-31 20:32:19 -0700207 match arg.ty {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700208 Type::Str(_) => out.builtin.rust_str_new_unchecked = true,
209 Type::RustVec(_) => out.builtin.unsafe_bitcopy = true,
210 _ => out.builtin.unsafe_bitcopy |= arg.ty == RustString,
David Tolnayb7a7cb62020-03-17 21:18:40 -0700211 }
David Tolnay09011c32020-03-06 14:40:28 -0800212 }
213 }
David Tolnayb7a7cb62020-03-17 21:18:40 -0700214 Api::RustFunction(efn) if !out.header => {
215 if efn.throws {
216 out.include.exception = true;
David Tolnayc8870b82020-09-09 08:44:33 -0700217 out.include.string = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700218 out.builtin.rust_str = true;
219 out.builtin.rust_error = true;
220 out.builtin.maybe_uninit = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700221 }
222 for arg in &efn.args {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700223 if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700224 out.builtin.manually_drop = true;
David Tolnaya4eb9432020-10-31 20:32:19 -0700225 }
226 if let Type::Str(_) = arg.ty {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700227 out.builtin.rust_str_repr = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700228 }
229 }
230 if let Some(ret) = &efn.ret {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700231 if out.types.needs_indirect_abi(ret) {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700232 out.builtin.maybe_uninit = true;
David Tolnaya4eb9432020-10-31 20:32:19 -0700233 } else if let Type::Str(_) = ret {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700234 out.builtin.rust_str_new_unchecked = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700235 }
David Tolnayf51447e2020-03-06 14:14:27 -0800236 }
237 }
David Tolnayb7a7cb62020-03-17 21:18:40 -0700238 _ => {}
David Tolnayf51447e2020-03-06 14:14:27 -0800239 }
240 }
David Tolnayec66d112020-10-31 21:00:26 -0700241}
David Tolnayf51447e2020-03-06 14:14:27 -0800242
David Tolnayec66d112020-10-31 21:00:26 -0700243fn write_builtins(out: &mut OutFile) {
David Tolnayfd68e562020-10-31 21:59:56 -0700244 if out.builtin == Default::default() {
245 return;
David Tolnayf51447e2020-03-06 14:14:27 -0800246 }
247
David Tolnayfd68e562020-10-31 21:59:56 -0700248 let include = &mut out.include;
249 let builtin = &mut out.builtin;
250 let out = &mut builtin.content;
David Tolnay16ab1462020-09-02 15:10:09 -0700251
David Tolnayfd68e562020-10-31 21:59:56 -0700252 out.begin_block("namespace rust");
253 out.begin_block("inline namespace cxxbridge05");
254 writeln!(out, "// #include \"rust/cxx.h\"");
255
David Tolnay3e278d72020-10-31 22:14:35 -0700256 ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
David Tolnayfd68e562020-10-31 21:59:56 -0700257
258 if builtin.rust_string {
David Tolnayd1402742020-03-25 22:21:42 -0700259 out.next_section();
260 writeln!(out, "struct unsafe_bitcopy_t;");
261 }
262
David Tolnayfd68e562020-10-31 21:59:56 -0700263 if builtin.rust_error {
David Tolnay84ddf9e2020-10-31 15:36:48 -0700264 out.begin_block("namespace");
265 writeln!(out, "template <typename T>");
266 writeln!(out, "class impl;");
267 out.end_block("namespace");
268 }
269
David Tolnay3e278d72020-10-31 22:14:35 -0700270 ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
271 ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
272 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
273 ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
274 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
275 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
276 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
277 ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
278 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
David Tolnayf51447e2020-03-06 14:14:27 -0800279
David Tolnayfd68e562020-10-31 21:59:56 -0700280 if builtin.manually_drop {
David Tolnayf51447e2020-03-06 14:14:27 -0800281 out.next_section();
David Tolnayfd68e562020-10-31 21:59:56 -0700282 include.utility = true;
David Tolnayf51447e2020-03-06 14:14:27 -0800283 writeln!(out, "template <typename T>");
284 writeln!(out, "union ManuallyDrop {{");
285 writeln!(out, " T value;");
286 writeln!(
287 out,
288 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
289 );
290 writeln!(out, " ~ManuallyDrop() {{}}");
291 writeln!(out, "}};");
292 }
293
David Tolnayfd68e562020-10-31 21:59:56 -0700294 if builtin.maybe_uninit {
David Tolnay09011c32020-03-06 14:40:28 -0800295 out.next_section();
296 writeln!(out, "template <typename T>");
297 writeln!(out, "union MaybeUninit {{");
298 writeln!(out, " T value;");
299 writeln!(out, " MaybeUninit() {{}}");
300 writeln!(out, " ~MaybeUninit() {{}}");
301 writeln!(out, "}};");
302 }
303
David Tolnayd68dfa82020-10-31 16:01:24 -0700304 out.begin_block("namespace");
305
David Tolnayfd68e562020-10-31 21:59:56 -0700306 if builtin.trycatch
307 || builtin.rust_error
308 || builtin.rust_str_new_unchecked
309 || builtin.rust_str_repr
David Tolnay3be0e1f2020-10-31 20:53:00 -0700310 {
David Tolnayd68dfa82020-10-31 16:01:24 -0700311 out.begin_block("namespace repr");
312 writeln!(out, "struct PtrLen final {{");
David Tolnay54742b72020-10-31 19:43:13 -0700313 writeln!(out, " const void *ptr;");
David Tolnayd68dfa82020-10-31 16:01:24 -0700314 writeln!(out, " size_t len;");
315 writeln!(out, "}};");
316 out.end_block("namespace repr");
317 }
318
David Tolnayfd68e562020-10-31 21:59:56 -0700319 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
David Tolnay0356d332020-10-31 19:46:41 -0700320 out.next_section();
321 writeln!(out, "template <>");
322 writeln!(out, "class impl<Str> final {{");
323 writeln!(out, "public:");
David Tolnayfd68e562020-10-31 21:59:56 -0700324 if builtin.rust_str_new_unchecked {
David Tolnaya4eb9432020-10-31 20:32:19 -0700325 writeln!(
326 out,
327 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
328 );
329 writeln!(out, " Str str;");
330 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
331 writeln!(out, " str.len = repr.len;");
332 writeln!(out, " return str;");
333 writeln!(out, " }}");
334 }
David Tolnayfd68e562020-10-31 21:59:56 -0700335 if builtin.rust_str_repr {
David Tolnaya4eb9432020-10-31 20:32:19 -0700336 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
337 writeln!(out, " return repr::PtrLen{{str.ptr, str.len}};");
338 writeln!(out, " }}");
339 }
David Tolnay0356d332020-10-31 19:46:41 -0700340 writeln!(out, "}};");
341 }
342
David Tolnayfd68e562020-10-31 21:59:56 -0700343 if builtin.rust_error {
David Tolnay0356d332020-10-31 19:46:41 -0700344 out.next_section();
David Tolnay84ddf9e2020-10-31 15:36:48 -0700345 writeln!(out, "template <>");
346 writeln!(out, "class impl<Error> final {{");
David Tolnaya0c9bc72020-10-31 14:37:14 -0700347 writeln!(out, "public:");
David Tolnayd68dfa82020-10-31 16:01:24 -0700348 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
David Tolnaya0c9bc72020-10-31 14:37:14 -0700349 writeln!(out, " Error error;");
David Tolnay54742b72020-10-31 19:43:13 -0700350 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
David Tolnay84ddf9e2020-10-31 15:36:48 -0700351 writeln!(out, " error.len = repr.len;");
David Tolnaya0c9bc72020-10-31 14:37:14 -0700352 writeln!(out, " return error;");
353 writeln!(out, " }}");
354 writeln!(out, "}};");
355 }
356
David Tolnayd68dfa82020-10-31 16:01:24 -0700357 out.end_block("namespace");
David Tolnay8f16ae72020-10-08 18:21:13 -0700358 out.end_block("namespace cxxbridge05");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700359
David Tolnayfd68e562020-10-31 21:59:56 -0700360 if builtin.trycatch {
David Tolnay3e3e0af2020-03-17 22:42:49 -0700361 out.begin_block("namespace behavior");
David Tolnayfd68e562020-10-31 21:59:56 -0700362 include.exception = true;
363 include.type_traits = true;
364 include.utility = true;
David Tolnay04722332020-03-18 11:31:54 -0700365 writeln!(out, "class missing {{}};");
366 writeln!(out, "missing trycatch(...);");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700367 writeln!(out);
David Tolnay04722332020-03-18 11:31:54 -0700368 writeln!(out, "template <typename Try, typename Fail>");
David Tolnaycc44c7a2020-10-04 13:20:03 -0700369 writeln!(out, "static typename ::std::enable_if<");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700370 writeln!(
371 out,
David Tolnaycc44c7a2020-10-04 13:20:03 -0700372 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
David Tolnay3e3e0af2020-03-17 22:42:49 -0700373 );
David Tolnay04722332020-03-18 11:31:54 -0700374 writeln!(out, " missing>::value>::type");
375 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
David Tolnay5d121442020-03-17 22:14:40 -0700376 writeln!(out, " func();");
377 writeln!(out, "}} catch (const ::std::exception &e) {{");
378 writeln!(out, " fail(e.what());");
379 writeln!(out, "}}");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700380 out.end_block("namespace behavior");
David Tolnay5d121442020-03-17 22:14:40 -0700381 }
382
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800383 out.end_block("namespace rust");
David Tolnay7db73692019-10-20 14:51:12 -0400384}
385
David Tolnaya7c2ea12020-10-30 21:32:53 -0700386fn write_struct(out: &mut OutFile, strct: &Struct) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700387 let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700388 writeln!(out, "#ifndef {}", guard);
389 writeln!(out, "#define {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400390 for line in strct.doc.to_string().lines() {
391 writeln!(out, "//{}", line);
392 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700393 writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
David Tolnay7db73692019-10-20 14:51:12 -0400394 for field in &strct.fields {
395 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700396 write_type_space(out, &field.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400397 writeln!(out, "{};", field.ident);
398 }
399 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700400 writeln!(out, "#endif // {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400401}
402
403fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
404 writeln!(out, "struct {};", ident);
405}
406
Adrian Taylorc8713432020-10-21 18:20:55 -0700407fn write_struct_using(out: &mut OutFile, ident: &CppName) {
408 writeln!(
409 out,
410 "using {} = {};",
411 ident.ident,
412 ident.to_fully_qualified()
413 );
David Tolnay8861bee2020-01-20 18:39:24 -0800414}
415
David Tolnaya7c2ea12020-10-30 21:32:53 -0700416fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700417 let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700418 writeln!(out, "#ifndef {}", guard);
419 writeln!(out, "#define {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700420 for line in ety.doc.to_string().lines() {
421 writeln!(out, "//{}", line);
422 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700423 writeln!(out, "struct {} final {{", ety.ident.cxx.ident);
424 writeln!(out, " {}() = delete;", ety.ident.cxx.ident);
425 writeln!(
426 out,
427 " {}(const {} &) = delete;",
428 ety.ident.cxx.ident, ety.ident.cxx.ident
429 );
Joel Galenson968738f2020-04-15 14:19:33 -0700430 for method in methods {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700431 write!(out, " ");
432 let sig = &method.sig;
Adrian Taylorc8713432020-10-21 18:20:55 -0700433 let local_name = method.ident.cxx.ident.to_string();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700434 write_rust_function_shim_decl(out, &local_name, sig, false);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700435 writeln!(out, ";");
436 }
437 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700438 writeln!(out, "#endif // {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700439}
440
Joel Galensonc03402a2020-04-23 17:31:09 -0700441fn write_enum(out: &mut OutFile, enm: &Enum) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700442 let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700443 writeln!(out, "#ifndef {}", guard);
444 writeln!(out, "#define {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700445 for line in enm.doc.to_string().lines() {
446 writeln!(out, "//{}", line);
447 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700448 write!(out, "enum class {} : ", enm.ident.cxx.ident);
David Tolnayf6a89f22020-05-10 23:39:27 -0700449 write_atom(out, enm.repr);
450 writeln!(out, " {{");
Joel Galensonc03402a2020-04-23 17:31:09 -0700451 for variant in &enm.variants {
Joel Galenson88547732020-05-05 08:23:42 -0700452 writeln!(out, " {} = {},", variant.ident, variant.discriminant);
Joel Galensonc03402a2020-04-23 17:31:09 -0700453 }
454 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700455 writeln!(out, "#endif // {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700456}
457
Joel Galenson905eb2e2020-05-04 14:58:14 -0700458fn check_enum(out: &mut OutFile, enm: &Enum) {
Adrian Taylorc8713432020-10-21 18:20:55 -0700459 write!(
460 out,
461 "static_assert(sizeof({}) == sizeof(",
462 enm.ident.cxx.ident
463 );
David Tolnayf6a89f22020-05-10 23:39:27 -0700464 write_atom(out, enm.repr);
465 writeln!(out, "), \"incorrect size\");");
Joel Galenson0f654ff2020-05-04 20:04:21 -0700466 for variant in &enm.variants {
David Tolnayf6a89f22020-05-10 23:39:27 -0700467 write!(out, "static_assert(static_cast<");
468 write_atom(out, enm.repr);
Joel Galenson0f654ff2020-05-04 20:04:21 -0700469 writeln!(
470 out,
David Tolnayf6a89f22020-05-10 23:39:27 -0700471 ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
Adrian Taylorc8713432020-10-21 18:20:55 -0700472 enm.ident.cxx.ident, variant.ident, variant.discriminant,
Joel Galenson0f654ff2020-05-04 20:04:21 -0700473 );
Joel Galenson0f654ff2020-05-04 20:04:21 -0700474 }
Joel Galenson905eb2e2020-05-04 14:58:14 -0700475}
476
Adrian Taylorc8713432020-10-21 18:20:55 -0700477fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
David Tolnayfd0034e2020-10-04 13:15:34 -0700478 // NOTE: The following two static assertions are just nice-to-have and not
479 // necessary for soundness. That's because triviality is always declared by
480 // the user in the form of an unsafe impl of cxx::ExternType:
481 //
482 // unsafe impl ExternType for MyType {
483 // type Id = cxx::type_id!("...");
484 // type Kind = cxx::kind::Trivial;
485 // }
486 //
487 // Since the user went on the record with their unsafe impl to unsafely
488 // claim they KNOW that the type is trivial, it's fine for that to be on
489 // them if that were wrong.
490 //
491 // There may be a legitimate reason we'll want to remove these assertions
492 // for support of types that the programmer knows are Rust-movable despite
493 // not being recognized as such by the C++ type system due to a move
494 // constructor or destructor.
495
Adrian Taylorc8713432020-10-21 18:20:55 -0700496 let id = &id.to_fully_qualified();
David Tolnayf57f7562020-10-04 19:56:26 -0700497 out.include.type_traits = true;
David Tolnay7426cc12020-10-03 19:04:04 -0700498 writeln!(out, "static_assert(");
499 writeln!(
500 out,
David Tolnaycc44c7a2020-10-04 13:20:03 -0700501 " ::std::is_trivially_move_constructible<{}>::value,",
David Tolnay7426cc12020-10-03 19:04:04 -0700502 id,
503 );
504 writeln!(
505 out,
506 " \"type {} marked as Trivial in Rust is not trivially move constructible in C++\");",
507 id,
508 );
509 writeln!(out, "static_assert(");
David Tolnaycc44c7a2020-10-04 13:20:03 -0700510 writeln!(out, " ::std::is_trivially_destructible<{}>::value,", id);
David Tolnay7426cc12020-10-03 19:04:04 -0700511 writeln!(
512 out,
513 " \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",
514 id,
515 );
Adrian Taylor405e8742020-09-25 14:01:25 -0700516}
517
Adrian Taylorc8713432020-10-21 18:20:55 -0700518fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
David Tolnayebef4a22020-03-17 15:33:47 -0700519 let mut has_cxx_throws = false;
520 for api in apis {
521 if let Api::CxxFunction(efn) = api {
522 if efn.throws {
523 has_cxx_throws = true;
524 break;
525 }
526 }
527 }
528
529 if has_cxx_throws {
530 out.next_section();
David Tolnaye68634c2020-03-18 12:03:40 -0700531 writeln!(
David Tolnayebef4a22020-03-17 15:33:47 -0700532 out,
David Tolnay8f16ae72020-10-08 18:21:13 -0700533 "const char *cxxbridge05$exception(const char *, size_t);",
David Tolnayebef4a22020-03-17 15:33:47 -0700534 );
535 }
536}
537
David Tolnaya7c2ea12020-10-30 21:32:53 -0700538fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: &Option<String>) {
David Tolnaycc1ae762020-10-31 15:53:50 -0700539 if let Some(annotation) = impl_annotations {
540 write!(out, "{} ", annotation);
Adrian Taylor21f0ff02020-07-21 16:21:48 -0700541 }
David Tolnayebef4a22020-03-17 15:33:47 -0700542 if efn.throws {
David Tolnayd68dfa82020-10-31 16:01:24 -0700543 write!(out, "::rust::repr::PtrLen ");
David Tolnayebef4a22020-03-17 15:33:47 -0700544 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700545 write_extern_return_type_space(out, &efn.ret);
David Tolnayebef4a22020-03-17 15:33:47 -0700546 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700547 let mangled = mangle::extern_fn(efn, out.types);
David Tolnay3caa50a2020-04-19 21:25:34 -0700548 write!(out, "{}(", mangled);
David Tolnaye439c772020-04-20 00:23:55 -0700549 if let Some(receiver) = &efn.receiver {
David Tolnay86710612020-04-20 00:30:32 -0700550 if receiver.mutability.is_none() {
551 write!(out, "const ");
552 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700553 write!(
554 out,
555 "{} &self",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700556 out.types.resolve(&receiver.ty).to_fully_qualified()
Adrian Taylorc8713432020-10-21 18:20:55 -0700557 );
Joel Galenson3d4f6122020-04-07 15:54:05 -0700558 }
David Tolnay7db73692019-10-20 14:51:12 -0400559 for (i, arg) in efn.args.iter().enumerate() {
Joel Galenson3d4f6122020-04-07 15:54:05 -0700560 if i > 0 || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400561 write!(out, ", ");
562 }
David Tolnaya46a2372020-03-06 10:03:48 -0800563 if arg.ty == RustString {
564 write!(out, "const ");
David Tolnay313b10e2020-04-25 16:30:51 -0700565 } else if let Type::RustVec(_) = arg.ty {
566 write!(out, "const ");
David Tolnaya46a2372020-03-06 10:03:48 -0800567 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700568 write_extern_arg(out, arg);
David Tolnay7db73692019-10-20 14:51:12 -0400569 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700570 let indirect_return = indirect_return(efn, out.types);
David Tolnay7db73692019-10-20 14:51:12 -0400571 if indirect_return {
myronahne3b78ea2020-05-23 01:08:13 +0700572 if !efn.args.is_empty() || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400573 write!(out, ", ");
574 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700575 write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400576 write!(out, "*return$");
577 }
578 writeln!(out, ") noexcept {{");
579 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700580 write_return_type(out, &efn.ret);
Joel Galenson3d4f6122020-04-07 15:54:05 -0700581 match &efn.receiver {
David Tolnaya4641c72020-09-08 14:05:53 -0700582 None => write!(out, "(*{}$)(", efn.ident.rust),
Adrian Taylorc8713432020-10-21 18:20:55 -0700583 Some(receiver) => write!(
584 out,
585 "({}::*{}$)(",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700586 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700587 efn.ident.rust
588 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700589 }
David Tolnay7db73692019-10-20 14:51:12 -0400590 for (i, arg) in efn.args.iter().enumerate() {
591 if i > 0 {
592 write!(out, ", ");
593 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700594 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400595 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700596 write!(out, ")");
David Tolnay4e7123f2020-04-19 21:11:37 -0700597 if let Some(receiver) = &efn.receiver {
598 if receiver.mutability.is_none() {
599 write!(out, " const");
600 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700601 }
602 write!(out, " = ");
603 match &efn.receiver {
Adrian Taylorc8713432020-10-21 18:20:55 -0700604 None => write!(out, "{}", efn.ident.cxx.to_fully_qualified()),
605 Some(receiver) => write!(
606 out,
607 "&{}::{}",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700608 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700609 efn.ident.cxx.ident
610 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700611 }
612 writeln!(out, ";");
David Tolnay7db73692019-10-20 14:51:12 -0400613 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700614 if efn.throws {
David Tolnayd68dfa82020-10-31 16:01:24 -0700615 writeln!(out, "::rust::repr::PtrLen throw$;");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700616 writeln!(out, " ::rust::behavior::trycatch(");
David Tolnay5d121442020-03-17 22:14:40 -0700617 writeln!(out, " [&] {{");
618 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700619 }
David Tolnay7db73692019-10-20 14:51:12 -0400620 if indirect_return {
David Tolnay0ecd05a2020-07-29 16:32:03 -0700621 out.include.new = true;
David Tolnay7db73692019-10-20 14:51:12 -0400622 write!(out, "new (return$) ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700623 write_indirect_return_type(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400624 write!(out, "(");
David Tolnay99642622020-03-25 13:07:35 -0700625 } else if efn.ret.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400626 write!(out, "return ");
David Tolnay99642622020-03-25 13:07:35 -0700627 }
628 match &efn.ret {
629 Some(Type::Ref(_)) => write!(out, "&"),
David Tolnay0356d332020-10-31 19:46:41 -0700630 Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::impl<::rust::Str>::repr("),
David Tolnayeb952ba2020-04-14 15:02:24 -0700631 Some(Type::SliceRefU8(_)) if !indirect_return => {
632 write!(out, "::rust::Slice<uint8_t>::Repr(")
633 }
David Tolnay99642622020-03-25 13:07:35 -0700634 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400635 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700636 match &efn.receiver {
David Tolnaya4641c72020-09-08 14:05:53 -0700637 None => write!(out, "{}$(", efn.ident.rust),
638 Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700639 }
David Tolnay7db73692019-10-20 14:51:12 -0400640 for (i, arg) in efn.args.iter().enumerate() {
641 if i > 0 {
642 write!(out, ", ");
643 }
644 if let Type::RustBox(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700645 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400646 write!(out, "::from_raw({})", arg.ident);
647 } else if let Type::UniquePtr(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700648 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400649 write!(out, "({})", arg.ident);
David Tolnay0356d332020-10-31 19:46:41 -0700650 } else if let Type::Str(_) = arg.ty {
651 write!(
652 out,
653 "::rust::impl<::rust::Str>::new_unchecked({})",
654 arg.ident,
655 );
David Tolnaya46a2372020-03-06 10:03:48 -0800656 } else if arg.ty == RustString {
David Tolnaycc3767f2020-03-06 10:41:51 -0800657 write!(
658 out,
659 "::rust::String(::rust::unsafe_bitcopy, *{})",
660 arg.ident,
661 );
David Tolnay313b10e2020-04-25 16:30:51 -0700662 } else if let Type::RustVec(_) = arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700663 write_type(out, &arg.ty);
David Tolnay313b10e2020-04-25 16:30:51 -0700664 write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
David Tolnaya7c2ea12020-10-30 21:32:53 -0700665 } else if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay4791f1c2020-03-17 21:53:16 -0700666 out.include.utility = true;
David Tolnay7e219b82020-03-01 13:14:51 -0800667 write!(out, "::std::move(*{})", arg.ident);
David Tolnay7db73692019-10-20 14:51:12 -0400668 } else {
669 write!(out, "{}", arg.ident);
670 }
671 }
672 write!(out, ")");
673 match &efn.ret {
674 Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
675 Some(Type::UniquePtr(_)) => write!(out, ".release()"),
David Tolnay0356d332020-10-31 19:46:41 -0700676 Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
David Tolnay7db73692019-10-20 14:51:12 -0400677 _ => {}
678 }
679 if indirect_return {
680 write!(out, ")");
681 }
682 writeln!(out, ";");
David Tolnayebef4a22020-03-17 15:33:47 -0700683 if efn.throws {
684 out.include.cstring = true;
David Tolnay5d121442020-03-17 22:14:40 -0700685 writeln!(out, " throw$.ptr = nullptr;");
686 writeln!(out, " }},");
David Tolnay82c16172020-03-17 22:54:12 -0700687 writeln!(out, " [&](const char *catch$) noexcept {{");
David Tolnay5d121442020-03-17 22:14:40 -0700688 writeln!(out, " throw$.len = ::std::strlen(catch$);");
David Tolnayebef4a22020-03-17 15:33:47 -0700689 writeln!(
690 out,
David Tolnay8f16ae72020-10-08 18:21:13 -0700691 " throw$.ptr = cxxbridge05$exception(catch$, throw$.len);",
David Tolnayebef4a22020-03-17 15:33:47 -0700692 );
David Tolnay5d121442020-03-17 22:14:40 -0700693 writeln!(out, " }});");
David Tolnayebef4a22020-03-17 15:33:47 -0700694 writeln!(out, " return throw$;");
695 }
David Tolnay7db73692019-10-20 14:51:12 -0400696 writeln!(out, "}}");
David Tolnay75dca2e2020-03-25 20:17:52 -0700697 for arg in &efn.args {
698 if let Type::Fn(f) = &arg.ty {
699 let var = &arg.ident;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700700 write_function_pointer_trampoline(out, efn, var, f);
David Tolnay75dca2e2020-03-25 20:17:52 -0700701 }
702 }
703}
704
705fn write_function_pointer_trampoline(
706 out: &mut OutFile,
707 efn: &ExternFn,
708 var: &Ident,
709 f: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700710) {
711 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700712 let r_trampoline = mangle::r_trampoline(efn, var, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700713 let indirect_call = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700714 write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700715
716 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700717 let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
718 write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400719}
720
David Tolnaya7c2ea12020-10-30 21:32:53 -0700721fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, _: &Option<String>) {
722 let link_name = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700723 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700724 write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700725}
726
727fn write_rust_function_decl_impl(
728 out: &mut OutFile,
David Tolnay891061b2020-04-19 22:42:33 -0700729 link_name: &Symbol,
David Tolnay75dca2e2020-03-25 20:17:52 -0700730 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700731 indirect_call: bool,
732) {
733 if sig.throws {
David Tolnayd68dfa82020-10-31 16:01:24 -0700734 write!(out, "::rust::repr::PtrLen ");
David Tolnay1e548172020-03-16 13:37:09 -0700735 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700736 write_extern_return_type_space(out, &sig.ret);
David Tolnay1e548172020-03-16 13:37:09 -0700737 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700738 write!(out, "{}(", link_name);
739 let mut needs_comma = false;
David Tolnaye439c772020-04-20 00:23:55 -0700740 if let Some(receiver) = &sig.receiver {
David Tolnay86710612020-04-20 00:30:32 -0700741 if receiver.mutability.is_none() {
742 write!(out, "const ");
743 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700744 write!(
745 out,
746 "{} &self",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700747 out.types.resolve(&receiver.ty).to_fully_qualified()
Adrian Taylorc8713432020-10-21 18:20:55 -0700748 );
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700749 needs_comma = true;
750 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700751 for arg in &sig.args {
752 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400753 write!(out, ", ");
754 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700755 write_extern_arg(out, arg);
David Tolnay75dca2e2020-03-25 20:17:52 -0700756 needs_comma = true;
David Tolnay7db73692019-10-20 14:51:12 -0400757 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700758 if indirect_return(sig, out.types) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700759 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400760 write!(out, ", ");
761 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700762 write_return_type(out, &sig.ret);
David Tolnay7db73692019-10-20 14:51:12 -0400763 write!(out, "*return$");
David Tolnay75dca2e2020-03-25 20:17:52 -0700764 needs_comma = true;
765 }
766 if indirect_call {
767 if needs_comma {
768 write!(out, ", ");
769 }
770 write!(out, "void *");
David Tolnay7db73692019-10-20 14:51:12 -0400771 }
772 writeln!(out, ") noexcept;");
773}
774
David Tolnaya7c2ea12020-10-30 21:32:53 -0700775fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn) {
David Tolnay7db73692019-10-20 14:51:12 -0400776 for line in efn.doc.to_string().lines() {
777 writeln!(out, "//{}", line);
778 }
David Tolnaya73853b2020-04-20 01:19:56 -0700779 let local_name = match &efn.sig.receiver {
Adrian Taylorc8713432020-10-21 18:20:55 -0700780 None => efn.ident.cxx.ident.to_string(),
781 Some(receiver) => format!(
782 "{}::{}",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700783 out.types.resolve(&receiver.ty).ident,
Adrian Taylorc8713432020-10-21 18:20:55 -0700784 efn.ident.cxx.ident
785 ),
David Tolnaya73853b2020-04-20 01:19:56 -0700786 };
David Tolnaya7c2ea12020-10-30 21:32:53 -0700787 let invoke = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700788 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700789 write_rust_function_shim_impl(out, &local_name, efn, &invoke, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700790}
791
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700792fn write_rust_function_shim_decl(
David Tolnay75dca2e2020-03-25 20:17:52 -0700793 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700794 local_name: &str,
David Tolnay75dca2e2020-03-25 20:17:52 -0700795 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700796 indirect_call: bool,
797) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700798 write_return_type(out, &sig.ret);
David Tolnay75dca2e2020-03-25 20:17:52 -0700799 write!(out, "{}(", local_name);
800 for (i, arg) in sig.args.iter().enumerate() {
David Tolnay7db73692019-10-20 14:51:12 -0400801 if i > 0 {
802 write!(out, ", ");
803 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700804 write_type_space(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400805 write!(out, "{}", arg.ident);
806 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700807 if indirect_call {
808 if !sig.args.is_empty() {
809 write!(out, ", ");
810 }
811 write!(out, "void *extern$");
812 }
David Tolnay1e548172020-03-16 13:37:09 -0700813 write!(out, ")");
David Tolnay86710612020-04-20 00:30:32 -0700814 if let Some(receiver) = &sig.receiver {
815 if receiver.mutability.is_none() {
816 write!(out, " const");
817 }
818 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700819 if !sig.throws {
David Tolnay1e548172020-03-16 13:37:09 -0700820 write!(out, " noexcept");
821 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700822}
823
824fn write_rust_function_shim_impl(
825 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700826 local_name: &str,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700827 sig: &Signature,
David Tolnay891061b2020-04-19 22:42:33 -0700828 invoke: &Symbol,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700829 indirect_call: bool,
830) {
831 if out.header && sig.receiver.is_some() {
832 // We've already defined this inside the struct.
833 return;
834 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700835 write_rust_function_shim_decl(out, local_name, sig, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400836 if out.header {
837 writeln!(out, ";");
David Tolnay439cde22020-04-20 00:46:25 -0700838 return;
David Tolnay7db73692019-10-20 14:51:12 -0400839 }
David Tolnay439cde22020-04-20 00:46:25 -0700840 writeln!(out, " {{");
841 for arg in &sig.args {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700842 if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
David Tolnay439cde22020-04-20 00:46:25 -0700843 out.include.utility = true;
844 write!(out, " ::rust::ManuallyDrop<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700845 write_type(out, &arg.ty);
David Tolnay439cde22020-04-20 00:46:25 -0700846 writeln!(out, "> {}$(::std::move({0}));", arg.ident);
847 }
848 }
849 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700850 let indirect_return = indirect_return(sig, out.types);
David Tolnay439cde22020-04-20 00:46:25 -0700851 if indirect_return {
852 write!(out, "::rust::MaybeUninit<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700853 write_type(out, sig.ret.as_ref().unwrap());
David Tolnay439cde22020-04-20 00:46:25 -0700854 writeln!(out, "> return$;");
855 write!(out, " ");
856 } else if let Some(ret) = &sig.ret {
857 write!(out, "return ");
858 match ret {
859 Type::RustBox(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700860 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700861 write!(out, "::from_raw(");
862 }
863 Type::UniquePtr(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700864 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700865 write!(out, "(");
866 }
867 Type::Ref(_) => write!(out, "*"),
David Tolnay0356d332020-10-31 19:46:41 -0700868 Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::new_unchecked("),
David Tolnay439cde22020-04-20 00:46:25 -0700869 _ => {}
870 }
871 }
872 if sig.throws {
David Tolnayd68dfa82020-10-31 16:01:24 -0700873 write!(out, "::rust::repr::PtrLen error$ = ");
David Tolnay439cde22020-04-20 00:46:25 -0700874 }
875 write!(out, "{}(", invoke);
876 if sig.receiver.is_some() {
877 write!(out, "*this");
878 }
879 for (i, arg) in sig.args.iter().enumerate() {
880 if i > 0 || sig.receiver.is_some() {
881 write!(out, ", ");
882 }
883 match &arg.ty {
David Tolnay0356d332020-10-31 19:46:41 -0700884 Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::repr("),
David Tolnay439cde22020-04-20 00:46:25 -0700885 Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700886 ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
David Tolnay439cde22020-04-20 00:46:25 -0700887 _ => {}
888 }
889 write!(out, "{}", arg.ident);
890 match &arg.ty {
891 Type::RustBox(_) => write!(out, ".into_raw()"),
892 Type::UniquePtr(_) => write!(out, ".release()"),
David Tolnay0356d332020-10-31 19:46:41 -0700893 Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700894 ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
David Tolnay439cde22020-04-20 00:46:25 -0700895 _ => {}
896 }
897 }
898 if indirect_return {
899 if !sig.args.is_empty() {
900 write!(out, ", ");
901 }
902 write!(out, "&return$.value");
903 }
904 if indirect_call {
905 if !sig.args.is_empty() || indirect_return {
906 write!(out, ", ");
907 }
908 write!(out, "extern$");
909 }
910 write!(out, ")");
David Tolnay22602b42020-09-21 18:04:05 -0400911 if !indirect_return {
912 if let Some(ret) = &sig.ret {
David Tolnay0356d332020-10-31 19:46:41 -0700913 if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) = ret {
David Tolnay22602b42020-09-21 18:04:05 -0400914 write!(out, ")");
915 }
David Tolnay439cde22020-04-20 00:46:25 -0700916 }
917 }
918 writeln!(out, ";");
919 if sig.throws {
David Tolnayd68dfa82020-10-31 16:01:24 -0700920 writeln!(out, " if (error$.ptr) {{");
David Tolnay84ddf9e2020-10-31 15:36:48 -0700921 writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
David Tolnay439cde22020-04-20 00:46:25 -0700922 writeln!(out, " }}");
923 }
924 if indirect_return {
925 out.include.utility = true;
926 writeln!(out, " return ::std::move(return$.value);");
927 }
928 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -0400929}
930
David Tolnaya7c2ea12020-10-30 21:32:53 -0700931fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -0400932 match ty {
933 None => write!(out, "void "),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700934 Some(ty) => write_type_space(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -0400935 }
936}
937
David Tolnay75dca2e2020-03-25 20:17:52 -0700938fn indirect_return(sig: &Signature, types: &Types) -> bool {
939 sig.ret
David Tolnay277e3cc2020-03-17 00:11:01 -0700940 .as_ref()
David Tolnay75dca2e2020-03-25 20:17:52 -0700941 .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
David Tolnay277e3cc2020-03-17 00:11:01 -0700942}
943
David Tolnaya7c2ea12020-10-30 21:32:53 -0700944fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
David Tolnay99642622020-03-25 13:07:35 -0700945 match ty {
946 Type::RustBox(ty) | Type::UniquePtr(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700947 write_type_space(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700948 write!(out, "*");
949 }
950 Type::Ref(ty) => {
951 if ty.mutability.is_none() {
952 write!(out, "const ");
953 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700954 write_type(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700955 write!(out, " *");
956 }
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700957 Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700958 _ => write_type(out, ty),
David Tolnay99642622020-03-25 13:07:35 -0700959 }
960}
961
David Tolnaya7c2ea12020-10-30 21:32:53 -0700962fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
963 write_indirect_return_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -0700964 match ty {
965 Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700966 Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
David Tolnay99642622020-03-25 13:07:35 -0700967 _ => write_space_after_type(out, ty),
968 }
969}
970
David Tolnaya7c2ea12020-10-30 21:32:53 -0700971fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -0400972 match ty {
973 Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700974 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400975 write!(out, "*");
976 }
David Tolnay4a441222020-01-25 16:24:27 -0800977 Some(Type::Ref(ty)) => {
978 if ty.mutability.is_none() {
979 write!(out, "const ");
980 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700981 write_type(out, &ty.inner);
David Tolnay4a441222020-01-25 16:24:27 -0800982 write!(out, " *");
983 }
David Tolnay0356d332020-10-31 19:46:41 -0700984 Some(Type::Str(_)) => write!(out, "::rust::repr::PtrLen "),
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700985 Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700986 Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
987 _ => write_return_type(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -0400988 }
989}
990
David Tolnaya7c2ea12020-10-30 21:32:53 -0700991fn write_extern_arg(out: &mut OutFile, arg: &Var) {
David Tolnay7db73692019-10-20 14:51:12 -0400992 match &arg.ty {
David Tolnay4377a9e2020-04-24 15:20:26 -0700993 Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700994 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400995 write!(out, "*");
996 }
David Tolnay0356d332020-10-31 19:46:41 -0700997 Type::Str(_) => write!(out, "::rust::repr::PtrLen "),
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700998 Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700999 _ => write_type_space(out, &arg.ty),
David Tolnay7db73692019-10-20 14:51:12 -04001000 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001001 if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay7db73692019-10-20 14:51:12 -04001002 write!(out, "*");
1003 }
1004 write!(out, "{}", arg.ident);
1005}
1006
David Tolnaya7c2ea12020-10-30 21:32:53 -07001007fn write_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -04001008 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -07001009 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnayf6a89f22020-05-10 23:39:27 -07001010 Some(atom) => write_atom(out, atom),
David Tolnaya7c2ea12020-10-30 21:32:53 -07001011 None => write!(out, "{}", out.types.resolve(ident).to_fully_qualified()),
David Tolnay7db73692019-10-20 14:51:12 -04001012 },
1013 Type::RustBox(ty) => {
David Tolnay750755e2020-03-01 13:04:08 -08001014 write!(out, "::rust::Box<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001015 write_type(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001016 write!(out, ">");
1017 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001018 Type::RustVec(ty) => {
1019 write!(out, "::rust::Vec<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001020 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001021 write!(out, ">");
1022 }
David Tolnay7db73692019-10-20 14:51:12 -04001023 Type::UniquePtr(ptr) => {
David Tolnay7e219b82020-03-01 13:14:51 -08001024 write!(out, "::std::unique_ptr<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001025 write_type(out, &ptr.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001026 write!(out, ">");
1027 }
David Tolnay4377a9e2020-04-24 15:20:26 -07001028 Type::CxxVector(ty) => {
Myron Ahneba35cf2020-02-05 19:41:51 +07001029 write!(out, "::std::vector<");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001030 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001031 write!(out, ">");
1032 }
David Tolnay7db73692019-10-20 14:51:12 -04001033 Type::Ref(r) => {
1034 if r.mutability.is_none() {
1035 write!(out, "const ");
1036 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001037 write_type(out, &r.inner);
David Tolnay7db73692019-10-20 14:51:12 -04001038 write!(out, " &");
1039 }
Adrian Taylorf5dd5522020-04-13 16:50:14 -07001040 Type::Slice(_) => {
1041 // For now, only U8 slices are supported, which are covered separately below
1042 unreachable!()
1043 }
David Tolnay7db73692019-10-20 14:51:12 -04001044 Type::Str(_) => {
David Tolnay750755e2020-03-01 13:04:08 -08001045 write!(out, "::rust::Str");
David Tolnay7db73692019-10-20 14:51:12 -04001046 }
Adrian Taylorf5dd5522020-04-13 16:50:14 -07001047 Type::SliceRefU8(_) => {
1048 write!(out, "::rust::Slice<uint8_t>");
1049 }
David Tolnay75dca2e2020-03-25 20:17:52 -07001050 Type::Fn(f) => {
1051 write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
1052 match &f.ret {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001053 Some(ret) => write_type(out, ret),
David Tolnay75dca2e2020-03-25 20:17:52 -07001054 None => write!(out, "void"),
1055 }
1056 write!(out, "(");
1057 for (i, arg) in f.args.iter().enumerate() {
1058 if i > 0 {
1059 write!(out, ", ");
1060 }
David Tolnaya7c2ea12020-10-30 21:32:53 -07001061 write_type(out, &arg.ty);
David Tolnay75dca2e2020-03-25 20:17:52 -07001062 }
1063 write!(out, ")>");
1064 }
David Tolnay2fb14e92020-03-15 23:11:38 -07001065 Type::Void(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -04001066 }
1067}
1068
David Tolnayf6a89f22020-05-10 23:39:27 -07001069fn write_atom(out: &mut OutFile, atom: Atom) {
1070 match atom {
1071 Bool => write!(out, "bool"),
1072 U8 => write!(out, "uint8_t"),
1073 U16 => write!(out, "uint16_t"),
1074 U32 => write!(out, "uint32_t"),
1075 U64 => write!(out, "uint64_t"),
1076 Usize => write!(out, "size_t"),
1077 I8 => write!(out, "int8_t"),
1078 I16 => write!(out, "int16_t"),
1079 I32 => write!(out, "int32_t"),
1080 I64 => write!(out, "int64_t"),
1081 Isize => write!(out, "::rust::isize"),
1082 F32 => write!(out, "float"),
1083 F64 => write!(out, "double"),
1084 CxxString => write!(out, "::std::string"),
1085 RustString => write!(out, "::rust::String"),
1086 }
1087}
1088
David Tolnaya7c2ea12020-10-30 21:32:53 -07001089fn write_type_space(out: &mut OutFile, ty: &Type) {
1090 write_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -07001091 write_space_after_type(out, ty);
1092}
1093
1094fn write_space_after_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -04001095 match ty {
David Tolnayeb952ba2020-04-14 15:02:24 -07001096 Type::Ident(_)
1097 | Type::RustBox(_)
1098 | Type::UniquePtr(_)
1099 | Type::Str(_)
David Tolnay4377a9e2020-04-24 15:20:26 -07001100 | Type::CxxVector(_)
Myron Ahneba35cf2020-02-05 19:41:51 +07001101 | Type::RustVec(_)
David Tolnayeb952ba2020-04-14 15:02:24 -07001102 | Type::SliceRefU8(_)
1103 | Type::Fn(_) => write!(out, " "),
David Tolnay7db73692019-10-20 14:51:12 -04001104 Type::Ref(_) => {}
Adrian Taylorf5dd5522020-04-13 16:50:14 -07001105 Type::Void(_) | Type::Slice(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -04001106 }
1107}
1108
David Tolnaycd08c442020-04-25 10:16:33 -07001109// Only called for legal referent types of unique_ptr and element types of
1110// std::vector and Vec.
Adrian Taylorc8713432020-10-21 18:20:55 -07001111fn to_typename(ty: &Type, types: &Types) -> String {
David Tolnay2eca4a02020-04-24 19:50:51 -07001112 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -07001113 Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
1114 Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
David Tolnaycd08c442020-04-25 10:16:33 -07001115 _ => unreachable!(),
David Tolnay2eca4a02020-04-24 19:50:51 -07001116 }
1117}
1118
David Tolnayacdf20a2020-04-25 12:40:53 -07001119// Only called for legal referent types of unique_ptr and element types of
1120// std::vector and Vec.
Adrian Taylorc8713432020-10-21 18:20:55 -07001121fn to_mangled(ty: &Type, types: &Types) -> Symbol {
David Tolnaybae50ef2020-04-25 12:38:41 -07001122 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -07001123 Type::Ident(ident) => ident.to_symbol(types),
1124 Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
David Tolnayacdf20a2020-04-25 12:40:53 -07001125 _ => unreachable!(),
David Tolnaybae50ef2020-04-25 12:38:41 -07001126 }
1127}
1128
David Tolnaya7c2ea12020-10-30 21:32:53 -07001129fn write_generic_instantiations(out: &mut OutFile) {
David Tolnay7db73692019-10-20 14:51:12 -04001130 out.begin_block("extern \"C\"");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001131 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -04001132 if let Type::RustBox(ty) = ty {
1133 if let Type::Ident(inner) = &ty.inner {
1134 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001135 write_rust_box_extern(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -04001136 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001137 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -07001138 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001139 if Atom::from(&inner.rust).is_none() {
David Tolnay6787be62020-04-25 11:01:02 -07001140 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001141 write_rust_vec_extern(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -07001142 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001143 }
David Tolnay7db73692019-10-20 14:51:12 -04001144 } else if let Type::UniquePtr(ptr) = ty {
1145 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001146 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -07001147 && (!out.types.aliases.contains_key(&inner.rust)
1148 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -07001149 {
David Tolnay7db73692019-10-20 14:51:12 -04001150 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001151 write_unique_ptr(out, inner);
Myron Ahneba35cf2020-02-05 19:41:51 +07001152 }
1153 }
David Tolnay4377a9e2020-04-24 15:20:26 -07001154 } else if let Type::CxxVector(ptr) = ty {
Myron Ahneba35cf2020-02-05 19:41:51 +07001155 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001156 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -07001157 && (!out.types.aliases.contains_key(&inner.rust)
1158 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -07001159 {
Myron Ahneba35cf2020-02-05 19:41:51 +07001160 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001161 write_cxx_vector(out, ty, inner);
David Tolnay7db73692019-10-20 14:51:12 -04001162 }
1163 }
1164 }
1165 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -08001166 out.end_block("extern \"C\"");
David Tolnay7db73692019-10-20 14:51:12 -04001167
David Tolnay750755e2020-03-01 13:04:08 -08001168 out.begin_block("namespace rust");
David Tolnay8f16ae72020-10-08 18:21:13 -07001169 out.begin_block("inline namespace cxxbridge05");
David Tolnaya7c2ea12020-10-30 21:32:53 -07001170 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -04001171 if let Type::RustBox(ty) = ty {
1172 if let Type::Ident(inner) = &ty.inner {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001173 write_rust_box_impl(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -04001174 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001175 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -07001176 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001177 if Atom::from(&inner.rust).is_none() {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001178 write_rust_vec_impl(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -07001179 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001180 }
David Tolnay7db73692019-10-20 14:51:12 -04001181 }
1182 }
David Tolnay8f16ae72020-10-08 18:21:13 -07001183 out.end_block("namespace cxxbridge05");
David Tolnay9ad1fbc2020-03-01 14:01:24 -08001184 out.end_block("namespace rust");
David Tolnay7db73692019-10-20 14:51:12 -04001185}
1186
Adrian Taylorc8713432020-10-21 18:20:55 -07001187fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
1188 let inner = ident.to_fully_qualified();
1189 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001190
David Tolnay8f16ae72020-10-08 18:21:13 -07001191 writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
1192 writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001193 writeln!(
1194 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001195 "void cxxbridge05$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001196 instance, inner,
1197 );
1198 writeln!(
1199 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001200 "void cxxbridge05$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001201 instance, inner,
1202 );
David Tolnay8f16ae72020-10-08 18:21:13 -07001203 writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001204}
1205
David Tolnaya7c2ea12020-10-30 21:32:53 -07001206fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
David Tolnay6787be62020-04-25 11:01:02 -07001207 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001208 let inner = to_typename(&element, out.types);
1209 let instance = to_mangled(&element, out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001210
David Tolnay8f16ae72020-10-08 18:21:13 -07001211 writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
1212 writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001213 writeln!(
1214 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001215 "void cxxbridge05$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
David Tolnayf97c2d52020-04-25 16:37:48 -07001216 instance, inner,
1217 );
1218 writeln!(
1219 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001220 "void cxxbridge05$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001221 instance, inner,
1222 );
1223 writeln!(
1224 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001225 "size_t cxxbridge05$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001226 instance, inner,
1227 );
David Tolnay219c0792020-04-24 20:31:37 -07001228 writeln!(
1229 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001230 "const {} *cxxbridge05$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
David Tolnay219c0792020-04-24 20:31:37 -07001231 inner, instance,
1232 );
David Tolnay503d0192020-04-24 22:18:56 -07001233 writeln!(
1234 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001235 "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
David Tolnay503d0192020-04-24 22:18:56 -07001236 instance,
1237 );
David Tolnay8f16ae72020-10-08 18:21:13 -07001238 writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001239}
1240
Adrian Taylorc8713432020-10-21 18:20:55 -07001241fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
1242 let inner = ident.to_fully_qualified();
1243 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001244
1245 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001246 writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001247 writeln!(out, " cxxbridge05$box${}$uninit(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001248 writeln!(out, "}}");
1249
1250 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001251 writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001252 writeln!(out, " cxxbridge05$box${}$drop(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001253 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001254}
1255
David Tolnaya7c2ea12020-10-30 21:32:53 -07001256fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
David Tolnay6787be62020-04-25 11:01:02 -07001257 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001258 let inner = to_typename(&element, out.types);
1259 let instance = to_mangled(&element, out.types);
David Tolnay4791f1c2020-03-17 21:53:16 -07001260
Myron Ahneba35cf2020-02-05 19:41:51 +07001261 writeln!(out, "template <>");
David Tolnayf97c2d52020-04-25 16:37:48 -07001262 writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001263 writeln!(out, " cxxbridge05$rust_vec${}$new(this);", instance);
David Tolnayf97c2d52020-04-25 16:37:48 -07001264 writeln!(out, "}}");
1265
1266 writeln!(out, "template <>");
Myron Ahneba35cf2020-02-05 19:41:51 +07001267 writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
1268 writeln!(
1269 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001270 " return cxxbridge05$rust_vec${}$drop(this);",
David Tolnay85db5a02020-04-25 13:17:27 -07001271 instance,
Myron Ahneba35cf2020-02-05 19:41:51 +07001272 );
1273 writeln!(out, "}}");
1274
1275 writeln!(out, "template <>");
1276 writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001277 writeln!(out, " return cxxbridge05$rust_vec${}$len(this);", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001278 writeln!(out, "}}");
David Tolnay219c0792020-04-24 20:31:37 -07001279
1280 writeln!(out, "template <>");
1281 writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
1282 writeln!(
1283 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001284 " return cxxbridge05$rust_vec${}$data(this);",
David Tolnay219c0792020-04-24 20:31:37 -07001285 instance,
1286 );
1287 writeln!(out, "}}");
David Tolnay503d0192020-04-24 22:18:56 -07001288
1289 writeln!(out, "template <>");
1290 writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001291 writeln!(out, " return cxxbridge05$rust_vec${}$stride();", instance);
David Tolnay503d0192020-04-24 22:18:56 -07001292 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001293}
1294
David Tolnaya7c2ea12020-10-30 21:32:53 -07001295fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
David Tolnay63da4d32020-04-25 09:41:12 -07001296 let ty = Type::Ident(ident.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001297 let instance = to_mangled(&ty, out.types);
David Tolnay63da4d32020-04-25 09:41:12 -07001298
David Tolnay8f16ae72020-10-08 18:21:13 -07001299 writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
1300 writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001301
David Tolnaya7c2ea12020-10-30 21:32:53 -07001302 write_unique_ptr_common(out, &ty);
David Tolnay63da4d32020-04-25 09:41:12 -07001303
David Tolnay8f16ae72020-10-08 18:21:13 -07001304 writeln!(out, "#endif // CXXBRIDGE05_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001305}
1306
1307// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
David Tolnaya7c2ea12020-10-30 21:32:53 -07001308fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
David Tolnay0ecd05a2020-07-29 16:32:03 -07001309 out.include.new = true;
Myron Ahneba35cf2020-02-05 19:41:51 +07001310 out.include.utility = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -07001311 let inner = to_typename(ty, out.types);
1312 let instance = to_mangled(ty, out.types);
David Tolnay7db73692019-10-20 14:51:12 -04001313
David Tolnay63da4d32020-04-25 09:41:12 -07001314 let can_construct_from_value = match ty {
David Tolnayca0f9da2020-10-16 13:16:17 -07001315 // Some aliases are to opaque types; some are to trivial types. We can't
1316 // know at code generation time, so we generate both C++ and Rust side
1317 // bindings for a "new" method anyway. But the Rust code can't be called
1318 // for Opaque types because the 'new' method is not implemented.
1319 Type::Ident(ident) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001320 out.types.structs.contains_key(&ident.rust)
1321 || out.types.aliases.contains_key(&ident.rust)
David Tolnayca0f9da2020-10-16 13:16:17 -07001322 }
David Tolnay63da4d32020-04-25 09:41:12 -07001323 _ => false,
1324 };
1325
David Tolnay7db73692019-10-20 14:51:12 -04001326 writeln!(
1327 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001328 "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001329 inner,
1330 );
1331 writeln!(
1332 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001333 "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001334 inner,
1335 );
1336 writeln!(
1337 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001338 "void cxxbridge05$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001339 instance, inner,
1340 );
David Tolnay7e219b82020-03-01 13:14:51 -08001341 writeln!(out, " new (ptr) ::std::unique_ptr<{}>();", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001342 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001343 if can_construct_from_value {
1344 writeln!(
David Tolnay53838912020-04-09 20:56:44 -07001345 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001346 "void cxxbridge05$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
David Tolnay53838912020-04-09 20:56:44 -07001347 instance, inner, inner,
1348 );
David Tolnay63da4d32020-04-25 09:41:12 -07001349 writeln!(
1350 out,
1351 " new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
1352 inner, inner,
1353 );
1354 writeln!(out, "}}");
David Tolnay53838912020-04-09 20:56:44 -07001355 }
David Tolnay7db73692019-10-20 14:51:12 -04001356 writeln!(
1357 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001358 "void cxxbridge05$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001359 instance, inner, inner,
1360 );
David Tolnay7e219b82020-03-01 13:14:51 -08001361 writeln!(out, " new (ptr) ::std::unique_ptr<{}>(raw);", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001362 writeln!(out, "}}");
1363 writeln!(
1364 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001365 "const {} *cxxbridge05$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001366 inner, instance, inner,
1367 );
1368 writeln!(out, " return ptr.get();");
1369 writeln!(out, "}}");
1370 writeln!(
1371 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001372 "{} *cxxbridge05$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001373 inner, instance, inner,
1374 );
1375 writeln!(out, " return ptr.release();");
1376 writeln!(out, "}}");
1377 writeln!(
1378 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001379 "void cxxbridge05$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001380 instance, inner,
1381 );
1382 writeln!(out, " ptr->~unique_ptr();");
1383 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001384}
Myron Ahneba35cf2020-02-05 19:41:51 +07001385
David Tolnaya7c2ea12020-10-30 21:32:53 -07001386fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName) {
David Tolnay63da4d32020-04-25 09:41:12 -07001387 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001388 let inner = to_typename(&element, out.types);
1389 let instance = to_mangled(&element, out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001390
David Tolnay8f16ae72020-10-08 18:21:13 -07001391 writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
1392 writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001393 writeln!(
1394 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001395 "size_t cxxbridge05$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001396 instance, inner,
1397 );
1398 writeln!(out, " return s.size();");
1399 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001400 writeln!(
1401 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001402 "const {} *cxxbridge05$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001403 inner, instance, inner,
1404 );
David Tolnayb3fcf7b2020-04-30 22:58:28 -07001405 writeln!(out, " return &s[pos];");
Myron Ahneba35cf2020-02-05 19:41:51 +07001406 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001407
David Tolnaya7c2ea12020-10-30 21:32:53 -07001408 write_unique_ptr_common(out, vector_ty);
David Tolnay63da4d32020-04-25 09:41:12 -07001409
David Tolnay8f16ae72020-10-08 18:21:13 -07001410 writeln!(out, "#endif // CXXBRIDGE05_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001411}