blob: 9d07173391ceeb4a04f472af8f8a565e0cac366c [file] [log] [blame]
David Tolnay0c033e32020-11-01 15:15:48 -08001use crate::gen::block::Block;
David Tolnayf7b81fb2020-11-01 22:39:04 -08002use crate::gen::nested::NamespaceEntries;
David Tolnay8810a542020-10-31 21:39:22 -07003use crate::gen::out::OutFile;
David Tolnay3374d8d2020-10-31 22:18:45 -07004use crate::gen::{builtin, include, Opt};
David Tolnay7db73692019-10-20 14:51:12 -04005use crate::syntax::atom::Atom::{self, *};
David Tolnay891061b2020-04-19 22:42:33 -07006use crate::syntax::symbol::Symbol;
Adrian Taylorc8713432020-10-21 18:20:55 -07007use crate::syntax::{
David Tolnay2f3e90b2020-10-31 22:16:51 -07008 mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
9 Types, Var,
Adrian Taylorc8713432020-10-21 18:20:55 -070010};
David Tolnay7db73692019-10-20 14:51:12 -040011use proc_macro2::Ident;
Joel Galenson0f654ff2020-05-04 20:04:21 -070012use std::collections::HashMap;
David Tolnay7db73692019-10-20 14:51:12 -040013
David Tolnayac7188c2020-11-01 16:58:16 -080014pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
David Tolnaye1476af2020-11-01 13:47:25 -080015 let mut out_file = OutFile::new(header, opt, types);
David Tolnay7db73692019-10-20 14:51:12 -040016 let out = &mut out_file;
17
David Tolnay74d6d512020-10-31 22:22:03 -070018 pick_includes_and_builtins(out);
David Tolnay4aae7c02020-10-28 12:35:42 -070019 out.include.extend(&opt.include);
David Tolnay7db73692019-10-20 14:51:12 -040020
David Tolnay7b0e5102020-11-01 23:22:12 -080021 write_forward_declarations(out, apis);
David Tolnaye1109d92020-11-01 20:51:56 -080022 write_data_structures(out, apis);
23 write_functions(out, apis);
David Tolnay169bb472020-11-01 21:04:24 -080024 write_generic_instantiations(out);
David Tolnay7db73692019-10-20 14:51:12 -040025
David Tolnay3374d8d2020-10-31 22:18:45 -070026 builtin::write(out);
David Tolnay2f3e90b2020-10-31 22:16:51 -070027 include::write(out);
Adrian Taylorc8713432020-10-21 18:20:55 -070028
David Tolnayac7188c2020-11-01 16:58:16 -080029 out_file.content()
Adrian Taylorc8713432020-10-21 18:20:55 -070030}
31
David Tolnay7b0e5102020-11-01 23:22:12 -080032fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
33 let needs_forward_declaration = |api: &&Api| match api {
34 Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
35 _ => false,
36 };
Adrian Taylorc8713432020-10-21 18:20:55 -070037
David Tolnay7b0e5102020-11-01 23:22:12 -080038 let apis_by_namespace =
39 NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
40
David Tolnayd920be52020-11-01 23:34:30 -080041 write(out, &apis_by_namespace, 0);
David Tolnay7b0e5102020-11-01 23:22:12 -080042
David Tolnayd920be52020-11-01 23:34:30 -080043 fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) {
David Tolnay7b0e5102020-11-01 23:22:12 -080044 let apis = ns_entries.direct_content();
45
46 for api in apis {
David Tolnayd920be52020-11-01 23:34:30 -080047 write!(out, "{:1$}", "", indent);
David Tolnay7b0e5102020-11-01 23:22:12 -080048 match api {
49 Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
50 Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
51 Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
52 _ => unreachable!(),
53 }
David Tolnay7db73692019-10-20 14:51:12 -040054 }
David Tolnay7db73692019-10-20 14:51:12 -040055
David Tolnay7b0e5102020-11-01 23:22:12 -080056 for (namespace, nested_ns_entries) in ns_entries.nested_content() {
David Tolnayd920be52020-11-01 23:34:30 -080057 writeln!(out, "{:2$}namespace {} {{", "", namespace, indent);
58 write(out, nested_ns_entries, indent + 2);
59 writeln!(out, "{:1$}}}", "", indent);
David Tolnay7b0e5102020-11-01 23:22:12 -080060 }
Adrian Taylorf9213622020-10-31 22:25:42 -070061 }
62}
63
David Tolnaye1109d92020-11-01 20:51:56 -080064fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
David Tolnayf94bef12020-04-17 14:46:42 -070065 let mut methods_for_type = HashMap::new();
David Tolnay630af882020-10-31 22:03:47 -070066 for api in apis {
David Tolnayf94bef12020-04-17 14:46:42 -070067 if let Api::RustFunction(efn) = api {
68 if let Some(receiver) = &efn.sig.receiver {
69 methods_for_type
Adrian Taylorc8713432020-10-21 18:20:55 -070070 .entry(&receiver.ty.rust)
David Tolnayf94bef12020-04-17 14:46:42 -070071 .or_insert_with(Vec::new)
72 .push(efn);
73 }
74 }
75 }
Joel Galenson968738f2020-04-15 14:19:33 -070076
David Tolnay7db73692019-10-20 14:51:12 -040077 for api in apis {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070078 match api {
David Tolnay7b0e5102020-11-01 23:22:12 -080079 Api::Include(include) => out.include.insert(include),
Joel Galensonc1c4e7a2020-04-15 10:21:00 -070080 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 }
David Tolnay1b0339c2020-11-01 20:37:50 -0800112}
113
David Tolnaye1109d92020-11-01 20:51:56 -0800114fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
David Tolnayce5a91f2020-10-31 22:42:08 -0700115 if !out.header {
David Tolnay7db73692019-10-20 14:51:12 -0400116 for api in apis {
David Tolnay04770742020-11-01 13:50:50 -0800117 match api {
118 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
119 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
120 _ => {}
121 }
David Tolnay7db73692019-10-20 14:51:12 -0400122 }
David Tolnay7db73692019-10-20 14:51:12 -0400123 }
124
125 for api in apis {
126 if let Api::RustFunction(efn) = api {
127 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700128 write_rust_function_shim(out, efn);
David Tolnay7db73692019-10-20 14:51:12 -0400129 }
130 }
David Tolnay7db73692019-10-20 14:51:12 -0400131}
132
David Tolnay74d6d512020-10-31 22:22:03 -0700133fn pick_includes_and_builtins(out: &mut OutFile) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700134 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -0400135 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700136 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnay89e386d2020-10-03 19:02:19 -0700137 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
138 | Some(I64) => out.include.cstdint = true,
139 Some(Usize) => out.include.cstddef = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700140 Some(Isize) => {
141 out.include.basetsd = true;
142 out.builtin.rust_isize = true;
143 }
David Tolnay89e386d2020-10-03 19:02:19 -0700144 Some(CxxString) => out.include.string = true,
David Tolnayb9da1462020-10-31 21:03:41 -0700145 Some(RustString) => {
146 out.include.array = true;
147 out.include.cstdint = true;
148 out.include.string = true;
149 out.builtin.rust_string = true;
150 }
151 Some(Bool) | Some(F32) | Some(F64) | None => {}
David Tolnay89e386d2020-10-03 19:02:19 -0700152 },
David Tolnayb7a7cb62020-03-17 21:18:40 -0700153 Type::RustBox(_) => {
David Tolnay0ecd05a2020-07-29 16:32:03 -0700154 out.include.new = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700155 out.include.type_traits = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700156 out.builtin.rust_box = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700157 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700158 Type::RustVec(_) => {
David Tolnay9c6bf2d2020-04-24 15:27:07 -0700159 out.include.array = true;
David Tolnay0ecd05a2020-07-29 16:32:03 -0700160 out.include.new = true;
David Tolnayc87c2152020-04-24 17:07:41 -0700161 out.include.type_traits = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700162 out.builtin.panic = true;
163 out.builtin.rust_vec = true;
164 out.builtin.unsafe_bitcopy = true;
Myron Ahneba35cf2020-02-05 19:41:51 +0700165 }
David Tolnayb9da1462020-10-31 21:03:41 -0700166 Type::UniquePtr(_) => out.include.memory = true,
David Tolnayb7a7cb62020-03-17 21:18:40 -0700167 Type::Str(_) => {
168 out.include.cstdint = true;
169 out.include.string = true;
David Tolnay3be0e1f2020-10-31 20:53:00 -0700170 out.builtin.rust_str = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700171 }
David Tolnayb9da1462020-10-31 21:03:41 -0700172 Type::CxxVector(_) => out.include.vector = true,
David Tolnay75dca2e2020-03-25 20:17:52 -0700173 Type::Fn(_) => {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700174 out.builtin.rust_fn = true;
David Tolnay75dca2e2020-03-25 20:17:52 -0700175 }
David Tolnayb9da1462020-10-31 21:03:41 -0700176 Type::Slice(_) => {
David Tolnay3be0e1f2020-10-31 20:53:00 -0700177 out.builtin.rust_slice = true;
David Tolnay4770b472020-04-14 16:32:59 -0700178 }
David Tolnayb9da1462020-10-31 21:03:41 -0700179 Type::SliceRefU8(_) => {
David Tolnayb7a7cb62020-03-17 21:18:40 -0700180 out.include.cstdint = true;
David Tolnayb9da1462020-10-31 21:03:41 -0700181 out.builtin.rust_slice = true;
David Tolnayb7a7cb62020-03-17 21:18:40 -0700182 }
David Tolnay11bd7ff2020-11-01 19:44:58 -0800183 Type::Ref(_) | Type::Void(_) => {}
David Tolnay7db73692019-10-20 14:51:12 -0400184 }
185 }
David Tolnayec66d112020-10-31 21:00:26 -0700186}
David Tolnayf51447e2020-03-06 14:14:27 -0800187
David Tolnay0b9b9f82020-11-01 20:41:00 -0800188fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800189 out.set_namespace(&strct.ident.cxx.namespace);
Adrian Taylorc8713432020-10-21 18:20:55 -0700190 let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700191 writeln!(out, "#ifndef {}", guard);
192 writeln!(out, "#define {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400193 for line in strct.doc.to_string().lines() {
194 writeln!(out, "//{}", line);
195 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700196 writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
David Tolnay7db73692019-10-20 14:51:12 -0400197 for field in &strct.fields {
198 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700199 write_type_space(out, &field.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400200 writeln!(out, "{};", field.ident);
201 }
202 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700203 writeln!(out, "#endif // {}", guard);
David Tolnay7db73692019-10-20 14:51:12 -0400204}
205
206fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
207 writeln!(out, "struct {};", ident);
208}
209
Adrian Taylorc8713432020-10-21 18:20:55 -0700210fn write_struct_using(out: &mut OutFile, ident: &CppName) {
211 writeln!(
212 out,
213 "using {} = {};",
214 ident.ident,
215 ident.to_fully_qualified()
216 );
David Tolnay8861bee2020-01-20 18:39:24 -0800217}
218
David Tolnay0b9b9f82020-11-01 20:41:00 -0800219fn write_struct_with_methods<'a>(
220 out: &mut OutFile<'a>,
221 ety: &'a ExternType,
222 methods: &[&ExternFn],
223) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800224 out.set_namespace(&ety.ident.cxx.namespace);
Adrian Taylorc8713432020-10-21 18:20:55 -0700225 let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700226 writeln!(out, "#ifndef {}", guard);
227 writeln!(out, "#define {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700228 for line in ety.doc.to_string().lines() {
229 writeln!(out, "//{}", line);
230 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700231 writeln!(out, "struct {} final {{", ety.ident.cxx.ident);
232 writeln!(out, " {}() = delete;", ety.ident.cxx.ident);
233 writeln!(
234 out,
235 " {}(const {} &) = delete;",
236 ety.ident.cxx.ident, ety.ident.cxx.ident
237 );
Joel Galenson968738f2020-04-15 14:19:33 -0700238 for method in methods {
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700239 write!(out, " ");
240 let sig = &method.sig;
Adrian Taylorc8713432020-10-21 18:20:55 -0700241 let local_name = method.ident.cxx.ident.to_string();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700242 write_rust_function_shim_decl(out, &local_name, sig, false);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700243 writeln!(out, ";");
244 }
245 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700246 writeln!(out, "#endif // {}", guard);
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700247}
248
David Tolnay0b9b9f82020-11-01 20:41:00 -0800249fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800250 out.set_namespace(&enm.ident.cxx.namespace);
Adrian Taylorc8713432020-10-21 18:20:55 -0700251 let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.to_symbol());
David Tolnaya25ea9c2020-08-27 22:59:38 -0700252 writeln!(out, "#ifndef {}", guard);
253 writeln!(out, "#define {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700254 for line in enm.doc.to_string().lines() {
255 writeln!(out, "//{}", line);
256 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700257 write!(out, "enum class {} : ", enm.ident.cxx.ident);
David Tolnayf6a89f22020-05-10 23:39:27 -0700258 write_atom(out, enm.repr);
259 writeln!(out, " {{");
Joel Galensonc03402a2020-04-23 17:31:09 -0700260 for variant in &enm.variants {
Joel Galenson88547732020-05-05 08:23:42 -0700261 writeln!(out, " {} = {},", variant.ident, variant.discriminant);
Joel Galensonc03402a2020-04-23 17:31:09 -0700262 }
263 writeln!(out, "}};");
David Tolnaya25ea9c2020-08-27 22:59:38 -0700264 writeln!(out, "#endif // {}", guard);
Joel Galensonc03402a2020-04-23 17:31:09 -0700265}
266
David Tolnay0b9b9f82020-11-01 20:41:00 -0800267fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800268 out.set_namespace(&enm.ident.cxx.namespace);
Adrian Taylorc8713432020-10-21 18:20:55 -0700269 write!(
270 out,
271 "static_assert(sizeof({}) == sizeof(",
272 enm.ident.cxx.ident
273 );
David Tolnayf6a89f22020-05-10 23:39:27 -0700274 write_atom(out, enm.repr);
275 writeln!(out, "), \"incorrect size\");");
Joel Galenson0f654ff2020-05-04 20:04:21 -0700276 for variant in &enm.variants {
David Tolnayf6a89f22020-05-10 23:39:27 -0700277 write!(out, "static_assert(static_cast<");
278 write_atom(out, enm.repr);
Joel Galenson0f654ff2020-05-04 20:04:21 -0700279 writeln!(
280 out,
David Tolnayf6a89f22020-05-10 23:39:27 -0700281 ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
Adrian Taylorc8713432020-10-21 18:20:55 -0700282 enm.ident.cxx.ident, variant.ident, variant.discriminant,
Joel Galenson0f654ff2020-05-04 20:04:21 -0700283 );
Joel Galenson0f654ff2020-05-04 20:04:21 -0700284 }
Joel Galenson905eb2e2020-05-04 14:58:14 -0700285}
286
Adrian Taylorc8713432020-10-21 18:20:55 -0700287fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
David Tolnayfd0034e2020-10-04 13:15:34 -0700288 // NOTE: The following two static assertions are just nice-to-have and not
289 // necessary for soundness. That's because triviality is always declared by
290 // the user in the form of an unsafe impl of cxx::ExternType:
291 //
292 // unsafe impl ExternType for MyType {
293 // type Id = cxx::type_id!("...");
294 // type Kind = cxx::kind::Trivial;
295 // }
296 //
297 // Since the user went on the record with their unsafe impl to unsafely
298 // claim they KNOW that the type is trivial, it's fine for that to be on
299 // them if that were wrong.
300 //
301 // There may be a legitimate reason we'll want to remove these assertions
302 // for support of types that the programmer knows are Rust-movable despite
303 // not being recognized as such by the C++ type system due to a move
304 // constructor or destructor.
305
Adrian Taylorc8713432020-10-21 18:20:55 -0700306 let id = &id.to_fully_qualified();
David Tolnayf57f7562020-10-04 19:56:26 -0700307 out.include.type_traits = true;
David Tolnay7426cc12020-10-03 19:04:04 -0700308 writeln!(out, "static_assert(");
309 writeln!(
310 out,
David Tolnaycc44c7a2020-10-04 13:20:03 -0700311 " ::std::is_trivially_move_constructible<{}>::value,",
David Tolnay7426cc12020-10-03 19:04:04 -0700312 id,
313 );
314 writeln!(
315 out,
316 " \"type {} marked as Trivial in Rust is not trivially move constructible in C++\");",
317 id,
318 );
319 writeln!(out, "static_assert(");
David Tolnaycc44c7a2020-10-04 13:20:03 -0700320 writeln!(out, " ::std::is_trivially_destructible<{}>::value,", id);
David Tolnay7426cc12020-10-03 19:04:04 -0700321 writeln!(
322 out,
323 " \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",
324 id,
325 );
Adrian Taylor405e8742020-09-25 14:01:25 -0700326}
327
David Tolnay0b9b9f82020-11-01 20:41:00 -0800328fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnay04770742020-11-01 13:50:50 -0800329 out.next_section();
David Tolnayb63ed5a2020-11-01 20:42:01 -0800330 out.set_namespace(&efn.ident.cxx.namespace);
David Tolnayca563ee2020-11-01 20:12:27 -0800331 out.begin_block(Block::ExternC);
David Tolnaye1476af2020-11-01 13:47:25 -0800332 if let Some(annotation) = &out.opt.cxx_impl_annotations {
David Tolnaycc1ae762020-10-31 15:53:50 -0700333 write!(out, "{} ", annotation);
Adrian Taylor21f0ff02020-07-21 16:21:48 -0700334 }
David Tolnayebef4a22020-03-17 15:33:47 -0700335 if efn.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700336 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700337 write!(out, "::rust::repr::PtrLen ");
David Tolnayebef4a22020-03-17 15:33:47 -0700338 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700339 write_extern_return_type_space(out, &efn.ret);
David Tolnayebef4a22020-03-17 15:33:47 -0700340 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700341 let mangled = mangle::extern_fn(efn, out.types);
David Tolnay3caa50a2020-04-19 21:25:34 -0700342 write!(out, "{}(", mangled);
David Tolnaye439c772020-04-20 00:23:55 -0700343 if let Some(receiver) = &efn.receiver {
David Tolnay86710612020-04-20 00:30:32 -0700344 if receiver.mutability.is_none() {
345 write!(out, "const ");
346 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700347 write!(
348 out,
349 "{} &self",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700350 out.types.resolve(&receiver.ty).to_fully_qualified()
Adrian Taylorc8713432020-10-21 18:20:55 -0700351 );
Joel Galenson3d4f6122020-04-07 15:54:05 -0700352 }
David Tolnay7db73692019-10-20 14:51:12 -0400353 for (i, arg) in efn.args.iter().enumerate() {
Joel Galenson3d4f6122020-04-07 15:54:05 -0700354 if i > 0 || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400355 write!(out, ", ");
356 }
David Tolnaya46a2372020-03-06 10:03:48 -0800357 if arg.ty == RustString {
358 write!(out, "const ");
David Tolnay313b10e2020-04-25 16:30:51 -0700359 } else if let Type::RustVec(_) = arg.ty {
360 write!(out, "const ");
David Tolnaya46a2372020-03-06 10:03:48 -0800361 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700362 write_extern_arg(out, arg);
David Tolnay7db73692019-10-20 14:51:12 -0400363 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700364 let indirect_return = indirect_return(efn, out.types);
David Tolnay7db73692019-10-20 14:51:12 -0400365 if indirect_return {
myronahne3b78ea2020-05-23 01:08:13 +0700366 if !efn.args.is_empty() || efn.receiver.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400367 write!(out, ", ");
368 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700369 write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400370 write!(out, "*return$");
371 }
372 writeln!(out, ") noexcept {{");
373 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700374 write_return_type(out, &efn.ret);
Joel Galenson3d4f6122020-04-07 15:54:05 -0700375 match &efn.receiver {
David Tolnaya4641c72020-09-08 14:05:53 -0700376 None => write!(out, "(*{}$)(", efn.ident.rust),
Adrian Taylorc8713432020-10-21 18:20:55 -0700377 Some(receiver) => write!(
378 out,
379 "({}::*{}$)(",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700380 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700381 efn.ident.rust
382 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700383 }
David Tolnay7db73692019-10-20 14:51:12 -0400384 for (i, arg) in efn.args.iter().enumerate() {
385 if i > 0 {
386 write!(out, ", ");
387 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700388 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400389 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700390 write!(out, ")");
David Tolnay4e7123f2020-04-19 21:11:37 -0700391 if let Some(receiver) = &efn.receiver {
392 if receiver.mutability.is_none() {
393 write!(out, " const");
394 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700395 }
396 write!(out, " = ");
397 match &efn.receiver {
Adrian Taylorc8713432020-10-21 18:20:55 -0700398 None => write!(out, "{}", efn.ident.cxx.to_fully_qualified()),
399 Some(receiver) => write!(
400 out,
401 "&{}::{}",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700402 out.types.resolve(&receiver.ty).to_fully_qualified(),
Adrian Taylorc8713432020-10-21 18:20:55 -0700403 efn.ident.cxx.ident
404 ),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700405 }
406 writeln!(out, ";");
David Tolnay7db73692019-10-20 14:51:12 -0400407 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700408 if efn.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700409 out.builtin.ptr_len = true;
David Tolnay74d6d512020-10-31 22:22:03 -0700410 out.builtin.trycatch = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700411 writeln!(out, "::rust::repr::PtrLen throw$;");
David Tolnay3e3e0af2020-03-17 22:42:49 -0700412 writeln!(out, " ::rust::behavior::trycatch(");
David Tolnay5d121442020-03-17 22:14:40 -0700413 writeln!(out, " [&] {{");
414 write!(out, " ");
David Tolnayebef4a22020-03-17 15:33:47 -0700415 }
David Tolnay7db73692019-10-20 14:51:12 -0400416 if indirect_return {
David Tolnay0ecd05a2020-07-29 16:32:03 -0700417 out.include.new = true;
David Tolnay7db73692019-10-20 14:51:12 -0400418 write!(out, "new (return$) ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700419 write_indirect_return_type(out, efn.ret.as_ref().unwrap());
David Tolnay7db73692019-10-20 14:51:12 -0400420 write!(out, "(");
David Tolnay99642622020-03-25 13:07:35 -0700421 } else if efn.ret.is_some() {
David Tolnay7db73692019-10-20 14:51:12 -0400422 write!(out, "return ");
David Tolnay99642622020-03-25 13:07:35 -0700423 }
424 match &efn.ret {
425 Some(Type::Ref(_)) => write!(out, "&"),
David Tolnay74d6d512020-10-31 22:22:03 -0700426 Some(Type::Str(_)) if !indirect_return => {
427 out.builtin.rust_str_repr = true;
428 write!(out, "::rust::impl<::rust::Str>::repr(");
429 }
David Tolnayeb952ba2020-04-14 15:02:24 -0700430 Some(Type::SliceRefU8(_)) if !indirect_return => {
David Tolnay36aa9e02020-10-31 23:08:21 -0700431 out.builtin.rust_slice_repr = true;
432 write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(")
David Tolnayeb952ba2020-04-14 15:02:24 -0700433 }
David Tolnay99642622020-03-25 13:07:35 -0700434 _ => {}
David Tolnay7db73692019-10-20 14:51:12 -0400435 }
Joel Galenson3d4f6122020-04-07 15:54:05 -0700436 match &efn.receiver {
David Tolnaya4641c72020-09-08 14:05:53 -0700437 None => write!(out, "{}$(", efn.ident.rust),
438 Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
Joel Galenson3d4f6122020-04-07 15:54:05 -0700439 }
David Tolnay7db73692019-10-20 14:51:12 -0400440 for (i, arg) in efn.args.iter().enumerate() {
441 if i > 0 {
442 write!(out, ", ");
443 }
444 if let Type::RustBox(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700445 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400446 write!(out, "::from_raw({})", arg.ident);
447 } else if let Type::UniquePtr(_) = &arg.ty {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700448 write_type(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400449 write!(out, "({})", arg.ident);
David Tolnay0356d332020-10-31 19:46:41 -0700450 } else if let Type::Str(_) = arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700451 out.builtin.rust_str_new_unchecked = true;
David Tolnay0356d332020-10-31 19:46:41 -0700452 write!(
453 out,
454 "::rust::impl<::rust::Str>::new_unchecked({})",
455 arg.ident,
456 );
David Tolnaya46a2372020-03-06 10:03:48 -0800457 } else if arg.ty == RustString {
David Tolnay74d6d512020-10-31 22:22:03 -0700458 out.builtin.unsafe_bitcopy = true;
David Tolnaycc3767f2020-03-06 10:41:51 -0800459 write!(
460 out,
461 "::rust::String(::rust::unsafe_bitcopy, *{})",
462 arg.ident,
463 );
David Tolnay313b10e2020-04-25 16:30:51 -0700464 } else if let Type::RustVec(_) = arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700465 out.builtin.unsafe_bitcopy = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700466 write_type(out, &arg.ty);
David Tolnay313b10e2020-04-25 16:30:51 -0700467 write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
David Tolnay36aa9e02020-10-31 23:08:21 -0700468 } else if let Type::SliceRefU8(_) = arg.ty {
469 write!(
470 out,
471 "::rust::Slice<uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
472 arg.ident,
473 );
David Tolnaya7c2ea12020-10-30 21:32:53 -0700474 } else if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay4791f1c2020-03-17 21:53:16 -0700475 out.include.utility = true;
David Tolnay7e219b82020-03-01 13:14:51 -0800476 write!(out, "::std::move(*{})", arg.ident);
David Tolnay7db73692019-10-20 14:51:12 -0400477 } else {
478 write!(out, "{}", arg.ident);
479 }
480 }
481 write!(out, ")");
482 match &efn.ret {
483 Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
484 Some(Type::UniquePtr(_)) => write!(out, ".release()"),
David Tolnay0356d332020-10-31 19:46:41 -0700485 Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
David Tolnay7db73692019-10-20 14:51:12 -0400486 _ => {}
487 }
488 if indirect_return {
489 write!(out, ")");
490 }
491 writeln!(out, ";");
David Tolnayebef4a22020-03-17 15:33:47 -0700492 if efn.throws {
493 out.include.cstring = true;
David Tolnay1f010c62020-11-01 20:27:46 -0800494 out.builtin.exception = true;
David Tolnay5d121442020-03-17 22:14:40 -0700495 writeln!(out, " throw$.ptr = nullptr;");
496 writeln!(out, " }},");
David Tolnay82c16172020-03-17 22:54:12 -0700497 writeln!(out, " [&](const char *catch$) noexcept {{");
David Tolnay5d121442020-03-17 22:14:40 -0700498 writeln!(out, " throw$.len = ::std::strlen(catch$);");
David Tolnayebef4a22020-03-17 15:33:47 -0700499 writeln!(
500 out,
David Tolnay1f010c62020-11-01 20:27:46 -0800501 " throw$.ptr = ::cxxbridge05$exception(catch$, throw$.len);",
David Tolnayebef4a22020-03-17 15:33:47 -0700502 );
David Tolnay5d121442020-03-17 22:14:40 -0700503 writeln!(out, " }});");
David Tolnayebef4a22020-03-17 15:33:47 -0700504 writeln!(out, " return throw$;");
505 }
David Tolnay7db73692019-10-20 14:51:12 -0400506 writeln!(out, "}}");
David Tolnay75dca2e2020-03-25 20:17:52 -0700507 for arg in &efn.args {
508 if let Type::Fn(f) = &arg.ty {
509 let var = &arg.ident;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700510 write_function_pointer_trampoline(out, efn, var, f);
David Tolnay75dca2e2020-03-25 20:17:52 -0700511 }
512 }
David Tolnayca563ee2020-11-01 20:12:27 -0800513 out.end_block(Block::ExternC);
David Tolnay75dca2e2020-03-25 20:17:52 -0700514}
515
516fn write_function_pointer_trampoline(
517 out: &mut OutFile,
518 efn: &ExternFn,
519 var: &Ident,
520 f: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700521) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700522 let r_trampoline = mangle::r_trampoline(efn, var, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700523 let indirect_call = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700524 write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700525
526 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700527 let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
528 write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400529}
530
David Tolnay0b9b9f82020-11-01 20:41:00 -0800531fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800532 out.set_namespace(&efn.ident.cxx.namespace);
David Tolnayca563ee2020-11-01 20:12:27 -0800533 out.begin_block(Block::ExternC);
David Tolnaya7c2ea12020-10-30 21:32:53 -0700534 let link_name = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700535 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700536 write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
David Tolnayca563ee2020-11-01 20:12:27 -0800537 out.end_block(Block::ExternC);
David Tolnay75dca2e2020-03-25 20:17:52 -0700538}
539
540fn write_rust_function_decl_impl(
541 out: &mut OutFile,
David Tolnay891061b2020-04-19 22:42:33 -0700542 link_name: &Symbol,
David Tolnay75dca2e2020-03-25 20:17:52 -0700543 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700544 indirect_call: bool,
545) {
David Tolnay04770742020-11-01 13:50:50 -0800546 out.next_section();
David Tolnay75dca2e2020-03-25 20:17:52 -0700547 if sig.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700548 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700549 write!(out, "::rust::repr::PtrLen ");
David Tolnay1e548172020-03-16 13:37:09 -0700550 } else {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700551 write_extern_return_type_space(out, &sig.ret);
David Tolnay1e548172020-03-16 13:37:09 -0700552 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700553 write!(out, "{}(", link_name);
554 let mut needs_comma = false;
David Tolnaye439c772020-04-20 00:23:55 -0700555 if let Some(receiver) = &sig.receiver {
David Tolnay86710612020-04-20 00:30:32 -0700556 if receiver.mutability.is_none() {
557 write!(out, "const ");
558 }
Adrian Taylorc8713432020-10-21 18:20:55 -0700559 write!(
560 out,
561 "{} &self",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700562 out.types.resolve(&receiver.ty).to_fully_qualified()
Adrian Taylorc8713432020-10-21 18:20:55 -0700563 );
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700564 needs_comma = true;
565 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700566 for arg in &sig.args {
567 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400568 write!(out, ", ");
569 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700570 write_extern_arg(out, arg);
David Tolnay75dca2e2020-03-25 20:17:52 -0700571 needs_comma = true;
David Tolnay7db73692019-10-20 14:51:12 -0400572 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700573 if indirect_return(sig, out.types) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700574 if needs_comma {
David Tolnay7db73692019-10-20 14:51:12 -0400575 write!(out, ", ");
576 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700577 write_return_type(out, &sig.ret);
David Tolnay7db73692019-10-20 14:51:12 -0400578 write!(out, "*return$");
David Tolnay75dca2e2020-03-25 20:17:52 -0700579 needs_comma = true;
580 }
581 if indirect_call {
582 if needs_comma {
583 write!(out, ", ");
584 }
585 write!(out, "void *");
David Tolnay7db73692019-10-20 14:51:12 -0400586 }
587 writeln!(out, ") noexcept;");
588}
589
David Tolnay0b9b9f82020-11-01 20:41:00 -0800590fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
David Tolnayb63ed5a2020-11-01 20:42:01 -0800591 out.set_namespace(&efn.ident.cxx.namespace);
David Tolnay7db73692019-10-20 14:51:12 -0400592 for line in efn.doc.to_string().lines() {
593 writeln!(out, "//{}", line);
594 }
David Tolnaya73853b2020-04-20 01:19:56 -0700595 let local_name = match &efn.sig.receiver {
Adrian Taylorc8713432020-10-21 18:20:55 -0700596 None => efn.ident.cxx.ident.to_string(),
597 Some(receiver) => format!(
598 "{}::{}",
David Tolnaya7c2ea12020-10-30 21:32:53 -0700599 out.types.resolve(&receiver.ty).ident,
Adrian Taylorc8713432020-10-21 18:20:55 -0700600 efn.ident.cxx.ident
601 ),
David Tolnaya73853b2020-04-20 01:19:56 -0700602 };
David Tolnaya7c2ea12020-10-30 21:32:53 -0700603 let invoke = mangle::extern_fn(efn, out.types);
David Tolnay75dca2e2020-03-25 20:17:52 -0700604 let indirect_call = false;
David Tolnaya7c2ea12020-10-30 21:32:53 -0700605 write_rust_function_shim_impl(out, &local_name, efn, &invoke, indirect_call);
David Tolnay75dca2e2020-03-25 20:17:52 -0700606}
607
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700608fn write_rust_function_shim_decl(
David Tolnay75dca2e2020-03-25 20:17:52 -0700609 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700610 local_name: &str,
David Tolnay75dca2e2020-03-25 20:17:52 -0700611 sig: &Signature,
David Tolnay75dca2e2020-03-25 20:17:52 -0700612 indirect_call: bool,
613) {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700614 write_return_type(out, &sig.ret);
David Tolnay75dca2e2020-03-25 20:17:52 -0700615 write!(out, "{}(", local_name);
616 for (i, arg) in sig.args.iter().enumerate() {
David Tolnay7db73692019-10-20 14:51:12 -0400617 if i > 0 {
618 write!(out, ", ");
619 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700620 write_type_space(out, &arg.ty);
David Tolnay7db73692019-10-20 14:51:12 -0400621 write!(out, "{}", arg.ident);
622 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700623 if indirect_call {
624 if !sig.args.is_empty() {
625 write!(out, ", ");
626 }
627 write!(out, "void *extern$");
628 }
David Tolnay1e548172020-03-16 13:37:09 -0700629 write!(out, ")");
David Tolnay86710612020-04-20 00:30:32 -0700630 if let Some(receiver) = &sig.receiver {
631 if receiver.mutability.is_none() {
632 write!(out, " const");
633 }
634 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700635 if !sig.throws {
David Tolnay1e548172020-03-16 13:37:09 -0700636 write!(out, " noexcept");
637 }
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700638}
639
640fn write_rust_function_shim_impl(
641 out: &mut OutFile,
David Tolnaya73853b2020-04-20 01:19:56 -0700642 local_name: &str,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700643 sig: &Signature,
David Tolnay891061b2020-04-19 22:42:33 -0700644 invoke: &Symbol,
Joel Galensonc1c4e7a2020-04-15 10:21:00 -0700645 indirect_call: bool,
646) {
647 if out.header && sig.receiver.is_some() {
648 // We've already defined this inside the struct.
649 return;
650 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700651 write_rust_function_shim_decl(out, local_name, sig, indirect_call);
David Tolnay7db73692019-10-20 14:51:12 -0400652 if out.header {
653 writeln!(out, ";");
David Tolnay439cde22020-04-20 00:46:25 -0700654 return;
David Tolnay7db73692019-10-20 14:51:12 -0400655 }
David Tolnay439cde22020-04-20 00:46:25 -0700656 writeln!(out, " {{");
657 for arg in &sig.args {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700658 if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
David Tolnay439cde22020-04-20 00:46:25 -0700659 out.include.utility = true;
David Tolnay74d6d512020-10-31 22:22:03 -0700660 out.builtin.manually_drop = true;
David Tolnay439cde22020-04-20 00:46:25 -0700661 write!(out, " ::rust::ManuallyDrop<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700662 write_type(out, &arg.ty);
David Tolnay439cde22020-04-20 00:46:25 -0700663 writeln!(out, "> {}$(::std::move({0}));", arg.ident);
664 }
665 }
666 write!(out, " ");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700667 let indirect_return = indirect_return(sig, out.types);
David Tolnay439cde22020-04-20 00:46:25 -0700668 if indirect_return {
David Tolnay74d6d512020-10-31 22:22:03 -0700669 out.builtin.maybe_uninit = true;
David Tolnay439cde22020-04-20 00:46:25 -0700670 write!(out, "::rust::MaybeUninit<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700671 write_type(out, sig.ret.as_ref().unwrap());
David Tolnay439cde22020-04-20 00:46:25 -0700672 writeln!(out, "> return$;");
673 write!(out, " ");
674 } else if let Some(ret) = &sig.ret {
675 write!(out, "return ");
676 match ret {
677 Type::RustBox(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700678 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700679 write!(out, "::from_raw(");
680 }
681 Type::UniquePtr(_) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700682 write_type(out, ret);
David Tolnay439cde22020-04-20 00:46:25 -0700683 write!(out, "(");
684 }
685 Type::Ref(_) => write!(out, "*"),
David Tolnay74d6d512020-10-31 22:22:03 -0700686 Type::Str(_) => {
687 out.builtin.rust_str_new_unchecked = true;
688 write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
689 }
David Tolnay36aa9e02020-10-31 23:08:21 -0700690 Type::SliceRefU8(_) => {
691 out.builtin.rust_slice_new = true;
692 write!(out, "::rust::impl<::rust::Slice<uint8_t>>::slice(");
693 }
David Tolnay439cde22020-04-20 00:46:25 -0700694 _ => {}
695 }
696 }
697 if sig.throws {
David Tolnay919085c2020-10-31 22:32:22 -0700698 out.builtin.ptr_len = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700699 write!(out, "::rust::repr::PtrLen error$ = ");
David Tolnay439cde22020-04-20 00:46:25 -0700700 }
701 write!(out, "{}(", invoke);
702 if sig.receiver.is_some() {
703 write!(out, "*this");
704 }
705 for (i, arg) in sig.args.iter().enumerate() {
706 if i > 0 || sig.receiver.is_some() {
707 write!(out, ", ");
708 }
709 match &arg.ty {
David Tolnay74d6d512020-10-31 22:22:03 -0700710 Type::Str(_) => {
711 out.builtin.rust_str_repr = true;
712 write!(out, "::rust::impl<::rust::Str>::repr(");
713 }
David Tolnay36aa9e02020-10-31 23:08:21 -0700714 Type::SliceRefU8(_) => {
715 out.builtin.rust_slice_repr = true;
716 write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(");
717 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700718 ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
David Tolnay439cde22020-04-20 00:46:25 -0700719 _ => {}
720 }
721 write!(out, "{}", arg.ident);
722 match &arg.ty {
723 Type::RustBox(_) => write!(out, ".into_raw()"),
724 Type::UniquePtr(_) => write!(out, ".release()"),
David Tolnay0356d332020-10-31 19:46:41 -0700725 Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700726 ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
David Tolnay439cde22020-04-20 00:46:25 -0700727 _ => {}
728 }
729 }
730 if indirect_return {
731 if !sig.args.is_empty() {
732 write!(out, ", ");
733 }
734 write!(out, "&return$.value");
735 }
736 if indirect_call {
737 if !sig.args.is_empty() || indirect_return {
738 write!(out, ", ");
739 }
740 write!(out, "extern$");
741 }
742 write!(out, ")");
David Tolnay22602b42020-09-21 18:04:05 -0400743 if !indirect_return {
744 if let Some(ret) = &sig.ret {
David Tolnay36aa9e02020-10-31 23:08:21 -0700745 if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) = ret
746 {
David Tolnay22602b42020-09-21 18:04:05 -0400747 write!(out, ")");
748 }
David Tolnay439cde22020-04-20 00:46:25 -0700749 }
750 }
751 writeln!(out, ";");
752 if sig.throws {
David Tolnay74d6d512020-10-31 22:22:03 -0700753 out.include.exception = true;
754 out.builtin.rust_error = true;
David Tolnayd68dfa82020-10-31 16:01:24 -0700755 writeln!(out, " if (error$.ptr) {{");
David Tolnay84ddf9e2020-10-31 15:36:48 -0700756 writeln!(out, " throw ::rust::impl<::rust::Error>::error(error$);");
David Tolnay439cde22020-04-20 00:46:25 -0700757 writeln!(out, " }}");
758 }
759 if indirect_return {
760 out.include.utility = true;
761 writeln!(out, " return ::std::move(return$.value);");
762 }
763 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -0400764}
765
David Tolnaya7c2ea12020-10-30 21:32:53 -0700766fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -0400767 match ty {
768 None => write!(out, "void "),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700769 Some(ty) => write_type_space(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -0400770 }
771}
772
David Tolnay75dca2e2020-03-25 20:17:52 -0700773fn indirect_return(sig: &Signature, types: &Types) -> bool {
774 sig.ret
David Tolnay277e3cc2020-03-17 00:11:01 -0700775 .as_ref()
David Tolnay75dca2e2020-03-25 20:17:52 -0700776 .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
David Tolnay277e3cc2020-03-17 00:11:01 -0700777}
778
David Tolnaya7c2ea12020-10-30 21:32:53 -0700779fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
David Tolnay99642622020-03-25 13:07:35 -0700780 match ty {
781 Type::RustBox(ty) | Type::UniquePtr(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700782 write_type_space(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700783 write!(out, "*");
784 }
785 Type::Ref(ty) => {
786 if ty.mutability.is_none() {
787 write!(out, "const ");
788 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700789 write_type(out, &ty.inner);
David Tolnay99642622020-03-25 13:07:35 -0700790 write!(out, " *");
791 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700792 _ => write_type(out, ty),
David Tolnay99642622020-03-25 13:07:35 -0700793 }
794}
795
David Tolnaya7c2ea12020-10-30 21:32:53 -0700796fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
797 write_indirect_return_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -0700798 match ty {
799 Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700800 Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
David Tolnay99642622020-03-25 13:07:35 -0700801 _ => write_space_after_type(out, ty),
802 }
803}
804
David Tolnaya7c2ea12020-10-30 21:32:53 -0700805fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
David Tolnay7db73692019-10-20 14:51:12 -0400806 match ty {
807 Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700808 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400809 write!(out, "*");
810 }
David Tolnay4a441222020-01-25 16:24:27 -0800811 Some(Type::Ref(ty)) => {
812 if ty.mutability.is_none() {
813 write!(out, "const ");
814 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700815 write_type(out, &ty.inner);
David Tolnay4a441222020-01-25 16:24:27 -0800816 write!(out, " *");
817 }
David Tolnay36aa9e02020-10-31 23:08:21 -0700818 Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) => {
David Tolnay919085c2020-10-31 22:32:22 -0700819 out.builtin.ptr_len = true;
820 write!(out, "::rust::repr::PtrLen ");
821 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700822 Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
823 _ => write_return_type(out, ty),
David Tolnay7db73692019-10-20 14:51:12 -0400824 }
825}
826
David Tolnaya7c2ea12020-10-30 21:32:53 -0700827fn write_extern_arg(out: &mut OutFile, arg: &Var) {
David Tolnay7db73692019-10-20 14:51:12 -0400828 match &arg.ty {
David Tolnay4377a9e2020-04-24 15:20:26 -0700829 Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700830 write_type_space(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400831 write!(out, "*");
832 }
David Tolnay36aa9e02020-10-31 23:08:21 -0700833 Type::Str(_) | Type::SliceRefU8(_) => {
David Tolnay919085c2020-10-31 22:32:22 -0700834 out.builtin.ptr_len = true;
835 write!(out, "::rust::repr::PtrLen ");
836 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700837 _ => write_type_space(out, &arg.ty),
David Tolnay7db73692019-10-20 14:51:12 -0400838 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700839 if out.types.needs_indirect_abi(&arg.ty) {
David Tolnay7db73692019-10-20 14:51:12 -0400840 write!(out, "*");
841 }
842 write!(out, "{}", arg.ident);
843}
844
David Tolnaya7c2ea12020-10-30 21:32:53 -0700845fn write_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -0400846 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700847 Type::Ident(ident) => match Atom::from(&ident.rust) {
David Tolnayf6a89f22020-05-10 23:39:27 -0700848 Some(atom) => write_atom(out, atom),
David Tolnaya7c2ea12020-10-30 21:32:53 -0700849 None => write!(out, "{}", out.types.resolve(ident).to_fully_qualified()),
David Tolnay7db73692019-10-20 14:51:12 -0400850 },
851 Type::RustBox(ty) => {
David Tolnay750755e2020-03-01 13:04:08 -0800852 write!(out, "::rust::Box<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700853 write_type(out, &ty.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400854 write!(out, ">");
855 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700856 Type::RustVec(ty) => {
857 write!(out, "::rust::Vec<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700858 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +0700859 write!(out, ">");
860 }
David Tolnay7db73692019-10-20 14:51:12 -0400861 Type::UniquePtr(ptr) => {
David Tolnay7e219b82020-03-01 13:14:51 -0800862 write!(out, "::std::unique_ptr<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700863 write_type(out, &ptr.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400864 write!(out, ">");
865 }
David Tolnay4377a9e2020-04-24 15:20:26 -0700866 Type::CxxVector(ty) => {
Myron Ahneba35cf2020-02-05 19:41:51 +0700867 write!(out, "::std::vector<");
David Tolnaya7c2ea12020-10-30 21:32:53 -0700868 write_type(out, &ty.inner);
Myron Ahneba35cf2020-02-05 19:41:51 +0700869 write!(out, ">");
870 }
David Tolnay7db73692019-10-20 14:51:12 -0400871 Type::Ref(r) => {
872 if r.mutability.is_none() {
873 write!(out, "const ");
874 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700875 write_type(out, &r.inner);
David Tolnay7db73692019-10-20 14:51:12 -0400876 write!(out, " &");
877 }
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700878 Type::Slice(_) => {
879 // For now, only U8 slices are supported, which are covered separately below
880 unreachable!()
881 }
David Tolnay7db73692019-10-20 14:51:12 -0400882 Type::Str(_) => {
David Tolnay750755e2020-03-01 13:04:08 -0800883 write!(out, "::rust::Str");
David Tolnay7db73692019-10-20 14:51:12 -0400884 }
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700885 Type::SliceRefU8(_) => {
886 write!(out, "::rust::Slice<uint8_t>");
887 }
David Tolnay75dca2e2020-03-25 20:17:52 -0700888 Type::Fn(f) => {
889 write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
890 match &f.ret {
David Tolnaya7c2ea12020-10-30 21:32:53 -0700891 Some(ret) => write_type(out, ret),
David Tolnay75dca2e2020-03-25 20:17:52 -0700892 None => write!(out, "void"),
893 }
894 write!(out, "(");
895 for (i, arg) in f.args.iter().enumerate() {
896 if i > 0 {
897 write!(out, ", ");
898 }
David Tolnaya7c2ea12020-10-30 21:32:53 -0700899 write_type(out, &arg.ty);
David Tolnay75dca2e2020-03-25 20:17:52 -0700900 }
901 write!(out, ")>");
902 }
David Tolnay2fb14e92020-03-15 23:11:38 -0700903 Type::Void(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -0400904 }
905}
906
David Tolnayf6a89f22020-05-10 23:39:27 -0700907fn write_atom(out: &mut OutFile, atom: Atom) {
908 match atom {
909 Bool => write!(out, "bool"),
910 U8 => write!(out, "uint8_t"),
911 U16 => write!(out, "uint16_t"),
912 U32 => write!(out, "uint32_t"),
913 U64 => write!(out, "uint64_t"),
914 Usize => write!(out, "size_t"),
915 I8 => write!(out, "int8_t"),
916 I16 => write!(out, "int16_t"),
917 I32 => write!(out, "int32_t"),
918 I64 => write!(out, "int64_t"),
919 Isize => write!(out, "::rust::isize"),
920 F32 => write!(out, "float"),
921 F64 => write!(out, "double"),
922 CxxString => write!(out, "::std::string"),
923 RustString => write!(out, "::rust::String"),
924 }
925}
926
David Tolnaya7c2ea12020-10-30 21:32:53 -0700927fn write_type_space(out: &mut OutFile, ty: &Type) {
928 write_type(out, ty);
David Tolnay99642622020-03-25 13:07:35 -0700929 write_space_after_type(out, ty);
930}
931
932fn write_space_after_type(out: &mut OutFile, ty: &Type) {
David Tolnay7db73692019-10-20 14:51:12 -0400933 match ty {
David Tolnayeb952ba2020-04-14 15:02:24 -0700934 Type::Ident(_)
935 | Type::RustBox(_)
936 | Type::UniquePtr(_)
937 | Type::Str(_)
David Tolnay4377a9e2020-04-24 15:20:26 -0700938 | Type::CxxVector(_)
Myron Ahneba35cf2020-02-05 19:41:51 +0700939 | Type::RustVec(_)
David Tolnayeb952ba2020-04-14 15:02:24 -0700940 | Type::SliceRefU8(_)
941 | Type::Fn(_) => write!(out, " "),
David Tolnay7db73692019-10-20 14:51:12 -0400942 Type::Ref(_) => {}
Adrian Taylorf5dd5522020-04-13 16:50:14 -0700943 Type::Void(_) | Type::Slice(_) => unreachable!(),
David Tolnay7db73692019-10-20 14:51:12 -0400944 }
945}
946
David Tolnaycd08c442020-04-25 10:16:33 -0700947// Only called for legal referent types of unique_ptr and element types of
948// std::vector and Vec.
Adrian Taylorc8713432020-10-21 18:20:55 -0700949fn to_typename(ty: &Type, types: &Types) -> String {
David Tolnay2eca4a02020-04-24 19:50:51 -0700950 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700951 Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
952 Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
David Tolnaycd08c442020-04-25 10:16:33 -0700953 _ => unreachable!(),
David Tolnay2eca4a02020-04-24 19:50:51 -0700954 }
955}
956
David Tolnayacdf20a2020-04-25 12:40:53 -0700957// Only called for legal referent types of unique_ptr and element types of
958// std::vector and Vec.
Adrian Taylorc8713432020-10-21 18:20:55 -0700959fn to_mangled(ty: &Type, types: &Types) -> Symbol {
David Tolnaybae50ef2020-04-25 12:38:41 -0700960 match ty {
Adrian Taylorc8713432020-10-21 18:20:55 -0700961 Type::Ident(ident) => ident.to_symbol(types),
962 Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
David Tolnayacdf20a2020-04-25 12:40:53 -0700963 _ => unreachable!(),
David Tolnaybae50ef2020-04-25 12:38:41 -0700964 }
965}
966
David Tolnaya7c2ea12020-10-30 21:32:53 -0700967fn write_generic_instantiations(out: &mut OutFile) {
David Tolnay169bb472020-11-01 21:04:24 -0800968 if out.header {
969 return;
970 }
971
972 out.next_section();
David Tolnay078c90f2020-11-01 13:31:08 -0800973 out.set_namespace(Default::default());
David Tolnay0c033e32020-11-01 15:15:48 -0800974 out.begin_block(Block::ExternC);
David Tolnaya7c2ea12020-10-30 21:32:53 -0700975 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -0400976 if let Type::RustBox(ty) = ty {
977 if let Type::Ident(inner) = &ty.inner {
978 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700979 write_rust_box_extern(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -0400980 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700981 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -0700982 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -0700983 if Atom::from(&inner.rust).is_none() {
David Tolnay6787be62020-04-25 11:01:02 -0700984 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700985 write_rust_vec_extern(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -0700986 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700987 }
David Tolnay7db73692019-10-20 14:51:12 -0400988 } else if let Type::UniquePtr(ptr) = ty {
989 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -0700990 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -0700991 && (!out.types.aliases.contains_key(&inner.rust)
992 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -0700993 {
David Tolnay7db73692019-10-20 14:51:12 -0400994 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -0700995 write_unique_ptr(out, inner);
Myron Ahneba35cf2020-02-05 19:41:51 +0700996 }
997 }
David Tolnay4377a9e2020-04-24 15:20:26 -0700998 } else if let Type::CxxVector(ptr) = ty {
Myron Ahneba35cf2020-02-05 19:41:51 +0700999 if let Type::Ident(inner) = &ptr.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001000 if Atom::from(&inner.rust).is_none()
David Tolnaya7c2ea12020-10-30 21:32:53 -07001001 && (!out.types.aliases.contains_key(&inner.rust)
1002 || out.types.explicit_impls.contains(ty))
David Tolnay7e69f892020-10-03 22:20:22 -07001003 {
Myron Ahneba35cf2020-02-05 19:41:51 +07001004 out.next_section();
David Tolnaya7c2ea12020-10-30 21:32:53 -07001005 write_cxx_vector(out, ty, inner);
David Tolnay7db73692019-10-20 14:51:12 -04001006 }
1007 }
1008 }
1009 }
David Tolnay0c033e32020-11-01 15:15:48 -08001010 out.end_block(Block::ExternC);
David Tolnay7db73692019-10-20 14:51:12 -04001011
David Tolnay0c033e32020-11-01 15:15:48 -08001012 out.begin_block(Block::Namespace("rust"));
1013 out.begin_block(Block::InlineNamespace("cxxbridge05"));
David Tolnaya7c2ea12020-10-30 21:32:53 -07001014 for ty in out.types {
David Tolnay7db73692019-10-20 14:51:12 -04001015 if let Type::RustBox(ty) = ty {
1016 if let Type::Ident(inner) = &ty.inner {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001017 write_rust_box_impl(out, &out.types.resolve(&inner));
David Tolnay7db73692019-10-20 14:51:12 -04001018 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001019 } else if let Type::RustVec(ty) = ty {
David Tolnay6787be62020-04-25 11:01:02 -07001020 if let Type::Ident(inner) = &ty.inner {
Adrian Taylorc8713432020-10-21 18:20:55 -07001021 if Atom::from(&inner.rust).is_none() {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001022 write_rust_vec_impl(out, inner);
David Tolnay6787be62020-04-25 11:01:02 -07001023 }
Myron Ahneba35cf2020-02-05 19:41:51 +07001024 }
David Tolnay7db73692019-10-20 14:51:12 -04001025 }
1026 }
David Tolnay0c033e32020-11-01 15:15:48 -08001027 out.end_block(Block::InlineNamespace("cxxbridge05"));
1028 out.end_block(Block::Namespace("rust"));
David Tolnay7db73692019-10-20 14:51:12 -04001029}
1030
Adrian Taylorc8713432020-10-21 18:20:55 -07001031fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
1032 let inner = ident.to_fully_qualified();
1033 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001034
David Tolnay8f16ae72020-10-08 18:21:13 -07001035 writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
1036 writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001037 writeln!(
1038 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001039 "void cxxbridge05$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001040 instance, inner,
1041 );
1042 writeln!(
1043 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001044 "void cxxbridge05$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
David Tolnay7db73692019-10-20 14:51:12 -04001045 instance, inner,
1046 );
David Tolnay8f16ae72020-10-08 18:21:13 -07001047 writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001048}
1049
David Tolnaya7c2ea12020-10-30 21:32:53 -07001050fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
David Tolnay6787be62020-04-25 11:01:02 -07001051 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001052 let inner = to_typename(&element, out.types);
1053 let instance = to_mangled(&element, out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001054
David Tolnay8f16ae72020-10-08 18:21:13 -07001055 writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
1056 writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001057 writeln!(
1058 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001059 "void cxxbridge05$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
David Tolnayf97c2d52020-04-25 16:37:48 -07001060 instance, inner,
1061 );
1062 writeln!(
1063 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001064 "void cxxbridge05$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001065 instance, inner,
1066 );
1067 writeln!(
1068 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001069 "size_t cxxbridge05$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
Myron Ahneba35cf2020-02-05 19:41:51 +07001070 instance, inner,
1071 );
David Tolnay219c0792020-04-24 20:31:37 -07001072 writeln!(
1073 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001074 "const {} *cxxbridge05$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
David Tolnay219c0792020-04-24 20:31:37 -07001075 inner, instance,
1076 );
David Tolnay503d0192020-04-24 22:18:56 -07001077 writeln!(
1078 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001079 "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
David Tolnay503d0192020-04-24 22:18:56 -07001080 instance,
1081 );
David Tolnay8f16ae72020-10-08 18:21:13 -07001082 writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001083}
1084
Adrian Taylorc8713432020-10-21 18:20:55 -07001085fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
1086 let inner = ident.to_fully_qualified();
1087 let instance = ident.to_symbol();
David Tolnay7db73692019-10-20 14:51:12 -04001088
1089 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001090 writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001091 writeln!(out, " cxxbridge05$box${}$uninit(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001092 writeln!(out, "}}");
1093
1094 writeln!(out, "template <>");
David Tolnay324437a2020-03-01 13:02:24 -08001095 writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001096 writeln!(out, " cxxbridge05$box${}$drop(this);", instance);
David Tolnay7db73692019-10-20 14:51:12 -04001097 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001098}
1099
David Tolnaya7c2ea12020-10-30 21:32:53 -07001100fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
David Tolnay6787be62020-04-25 11:01:02 -07001101 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001102 let inner = to_typename(&element, out.types);
1103 let instance = to_mangled(&element, out.types);
David Tolnay4791f1c2020-03-17 21:53:16 -07001104
Myron Ahneba35cf2020-02-05 19:41:51 +07001105 writeln!(out, "template <>");
David Tolnayf97c2d52020-04-25 16:37:48 -07001106 writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001107 writeln!(out, " cxxbridge05$rust_vec${}$new(this);", instance);
David Tolnayf97c2d52020-04-25 16:37:48 -07001108 writeln!(out, "}}");
1109
1110 writeln!(out, "template <>");
Myron Ahneba35cf2020-02-05 19:41:51 +07001111 writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
1112 writeln!(
1113 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001114 " return cxxbridge05$rust_vec${}$drop(this);",
David Tolnay85db5a02020-04-25 13:17:27 -07001115 instance,
Myron Ahneba35cf2020-02-05 19:41:51 +07001116 );
1117 writeln!(out, "}}");
1118
1119 writeln!(out, "template <>");
1120 writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001121 writeln!(out, " return cxxbridge05$rust_vec${}$len(this);", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001122 writeln!(out, "}}");
David Tolnay219c0792020-04-24 20:31:37 -07001123
1124 writeln!(out, "template <>");
1125 writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
1126 writeln!(
1127 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001128 " return cxxbridge05$rust_vec${}$data(this);",
David Tolnay219c0792020-04-24 20:31:37 -07001129 instance,
1130 );
1131 writeln!(out, "}}");
David Tolnay503d0192020-04-24 22:18:56 -07001132
1133 writeln!(out, "template <>");
1134 writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
David Tolnay8f16ae72020-10-08 18:21:13 -07001135 writeln!(out, " return cxxbridge05$rust_vec${}$stride();", instance);
David Tolnay503d0192020-04-24 22:18:56 -07001136 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001137}
1138
David Tolnaya7c2ea12020-10-30 21:32:53 -07001139fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
David Tolnay63da4d32020-04-25 09:41:12 -07001140 let ty = Type::Ident(ident.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001141 let instance = to_mangled(&ty, out.types);
David Tolnay63da4d32020-04-25 09:41:12 -07001142
David Tolnay8f16ae72020-10-08 18:21:13 -07001143 writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
1144 writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001145
David Tolnaya7c2ea12020-10-30 21:32:53 -07001146 write_unique_ptr_common(out, &ty);
David Tolnay63da4d32020-04-25 09:41:12 -07001147
David Tolnay8f16ae72020-10-08 18:21:13 -07001148 writeln!(out, "#endif // CXXBRIDGE05_UNIQUE_PTR_{}", instance);
David Tolnay63da4d32020-04-25 09:41:12 -07001149}
1150
1151// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
David Tolnaya7c2ea12020-10-30 21:32:53 -07001152fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
David Tolnay0ecd05a2020-07-29 16:32:03 -07001153 out.include.new = true;
Myron Ahneba35cf2020-02-05 19:41:51 +07001154 out.include.utility = true;
David Tolnaya7c2ea12020-10-30 21:32:53 -07001155 let inner = to_typename(ty, out.types);
1156 let instance = to_mangled(ty, out.types);
David Tolnay7db73692019-10-20 14:51:12 -04001157
David Tolnay63da4d32020-04-25 09:41:12 -07001158 let can_construct_from_value = match ty {
David Tolnayca0f9da2020-10-16 13:16:17 -07001159 // Some aliases are to opaque types; some are to trivial types. We can't
1160 // know at code generation time, so we generate both C++ and Rust side
1161 // bindings for a "new" method anyway. But the Rust code can't be called
1162 // for Opaque types because the 'new' method is not implemented.
1163 Type::Ident(ident) => {
David Tolnaya7c2ea12020-10-30 21:32:53 -07001164 out.types.structs.contains_key(&ident.rust)
1165 || out.types.aliases.contains_key(&ident.rust)
David Tolnayca0f9da2020-10-16 13:16:17 -07001166 }
David Tolnay63da4d32020-04-25 09:41:12 -07001167 _ => false,
1168 };
1169
David Tolnay7db73692019-10-20 14:51:12 -04001170 writeln!(
1171 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001172 "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001173 inner,
1174 );
1175 writeln!(
1176 out,
David Tolnay7e219b82020-03-01 13:14:51 -08001177 "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
David Tolnay7db73692019-10-20 14:51:12 -04001178 inner,
1179 );
1180 writeln!(
1181 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001182 "void cxxbridge05$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001183 instance, inner,
1184 );
David Tolnay7e219b82020-03-01 13:14:51 -08001185 writeln!(out, " new (ptr) ::std::unique_ptr<{}>();", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001186 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001187 if can_construct_from_value {
1188 writeln!(
David Tolnay53838912020-04-09 20:56:44 -07001189 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001190 "void cxxbridge05$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
David Tolnay53838912020-04-09 20:56:44 -07001191 instance, inner, inner,
1192 );
David Tolnay63da4d32020-04-25 09:41:12 -07001193 writeln!(
1194 out,
1195 " new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
1196 inner, inner,
1197 );
1198 writeln!(out, "}}");
David Tolnay53838912020-04-09 20:56:44 -07001199 }
David Tolnay7db73692019-10-20 14:51:12 -04001200 writeln!(
1201 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001202 "void cxxbridge05$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001203 instance, inner, inner,
1204 );
David Tolnay7e219b82020-03-01 13:14:51 -08001205 writeln!(out, " new (ptr) ::std::unique_ptr<{}>(raw);", inner);
David Tolnay7db73692019-10-20 14:51:12 -04001206 writeln!(out, "}}");
1207 writeln!(
1208 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001209 "const {} *cxxbridge05$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001210 inner, instance, inner,
1211 );
1212 writeln!(out, " return ptr.get();");
1213 writeln!(out, "}}");
1214 writeln!(
1215 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001216 "{} *cxxbridge05$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001217 inner, instance, inner,
1218 );
1219 writeln!(out, " return ptr.release();");
1220 writeln!(out, "}}");
1221 writeln!(
1222 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001223 "void cxxbridge05$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
David Tolnay7db73692019-10-20 14:51:12 -04001224 instance, inner,
1225 );
1226 writeln!(out, " ptr->~unique_ptr();");
1227 writeln!(out, "}}");
David Tolnay7db73692019-10-20 14:51:12 -04001228}
Myron Ahneba35cf2020-02-05 19:41:51 +07001229
David Tolnaya7c2ea12020-10-30 21:32:53 -07001230fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName) {
David Tolnay63da4d32020-04-25 09:41:12 -07001231 let element = Type::Ident(element.clone());
David Tolnaya7c2ea12020-10-30 21:32:53 -07001232 let inner = to_typename(&element, out.types);
1233 let instance = to_mangled(&element, out.types);
Myron Ahneba35cf2020-02-05 19:41:51 +07001234
David Tolnay8f16ae72020-10-08 18:21:13 -07001235 writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
1236 writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001237 writeln!(
1238 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001239 "size_t cxxbridge05$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001240 instance, inner,
1241 );
1242 writeln!(out, " return s.size();");
1243 writeln!(out, "}}");
Myron Ahneba35cf2020-02-05 19:41:51 +07001244 writeln!(
1245 out,
David Tolnay8f16ae72020-10-08 18:21:13 -07001246 "const {} *cxxbridge05$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
Myron Ahneba35cf2020-02-05 19:41:51 +07001247 inner, instance, inner,
1248 );
David Tolnayb3fcf7b2020-04-30 22:58:28 -07001249 writeln!(out, " return &s[pos];");
Myron Ahneba35cf2020-02-05 19:41:51 +07001250 writeln!(out, "}}");
David Tolnay63da4d32020-04-25 09:41:12 -07001251
David Tolnaya7c2ea12020-10-30 21:32:53 -07001252 write_unique_ptr_common(out, vector_ty);
David Tolnay63da4d32020-04-25 09:41:12 -07001253
David Tolnay8f16ae72020-10-08 18:21:13 -07001254 writeln!(out, "#endif // CXXBRIDGE05_VECTOR_{}", instance);
Myron Ahneba35cf2020-02-05 19:41:51 +07001255}