blob: 35620db81f8040ad4cf17551123b9ff26ee3bb28 [file] [log] [blame]
David Tolnay0c033e32020-11-01 15:15:48 -08001use crate::gen::block::Block;
David Tolnay3374d8d2020-10-31 22:18:45 -07002use crate::gen::ifndef;
3use crate::gen::out::{Content, OutFile};
David Tolnay8c14d9a2020-10-31 21:52:38 -07004
David Tolnay3be0e1f2020-10-31 20:53:00 -07005#[derive(Default, PartialEq)]
David Tolnay97c5b862020-11-01 14:59:01 -08006pub struct Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -07007 pub panic: bool,
8 pub rust_string: bool,
9 pub rust_str: bool,
10 pub rust_slice: bool,
11 pub rust_box: bool,
12 pub rust_vec: bool,
13 pub rust_fn: bool,
14 pub rust_isize: bool,
15 pub unsafe_bitcopy: bool,
16 pub rust_error: bool,
17 pub manually_drop: bool,
18 pub maybe_uninit: bool,
19 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070020 pub ptr_len: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070021 pub rust_str_new_unchecked: bool,
22 pub rust_str_repr: bool,
David Tolnay36aa9e02020-10-31 23:08:21 -070023 pub rust_slice_new: bool,
24 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080025 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080026 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080027 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080028 pub is_complete: bool,
29 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080030 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070031}
32
David Tolnay97c5b862020-11-01 14:59:01 -080033impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070034 pub fn new() -> Self {
35 Builtins::default()
36 }
37}
David Tolnay3374d8d2020-10-31 22:18:45 -070038
39pub(super) fn write(out: &mut OutFile) {
40 if out.builtin == Default::default() {
41 return;
42 }
43
44 let include = &mut out.include;
45 let builtin = &mut out.builtin;
46 let out = &mut builtin.content;
47
David Tolnaydcfa8e92020-11-02 09:50:06 -080048 if builtin.rust_string {
49 include.array = true;
50 include.cstdint = true;
51 include.string = true;
52 }
53
54 if builtin.rust_str {
55 include.cstdint = true;
56 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080057 builtin.friend_impl = true;
58 }
59
60 if builtin.rust_slice {
61 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080062 }
63
64 if builtin.rust_box {
65 include.new = true;
66 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080067 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080068 }
69
70 if builtin.rust_vec {
71 include.array = true;
72 include.new = true;
73 include.type_traits = true;
David Tolnayfb6b73c2020-11-10 14:32:16 -080074 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080075 builtin.panic = true;
76 builtin.unsafe_bitcopy = true;
77 }
78
David Tolnaya5a13012020-11-10 15:03:09 -080079 if builtin.rust_fn {
80 include.utility = true;
81 }
82
David Tolnaydcfa8e92020-11-02 09:50:06 -080083 if builtin.rust_error {
84 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080085 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080086 }
87
88 if builtin.rust_isize {
89 include.basetsd = true;
90 }
91
David Tolnay174bd952020-11-02 09:23:12 -080092 if builtin.relocatable {
93 include.type_traits = true;
94 }
95
David Tolnay0c033e32020-11-01 15:15:48 -080096 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -080097 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -070098 writeln!(out, "// #include \"rust/cxx.h\"");
99
David Tolnay0f0162f2020-11-16 23:43:37 -0800100 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700101
102 if builtin.rust_string {
103 out.next_section();
104 writeln!(out, "struct unsafe_bitcopy_t;");
105 }
106
David Tolnay22664ae2020-11-04 16:30:45 -0800107 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800108 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700109 writeln!(out, "template <typename T>");
110 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800111 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700112 }
113
David Tolnay0f0162f2020-11-16 23:43:37 -0800114 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
115 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
116 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
117 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
118 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
119 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
120 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
121 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
122 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
123 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700124
125 if builtin.manually_drop {
126 out.next_section();
127 include.utility = true;
128 writeln!(out, "template <typename T>");
129 writeln!(out, "union ManuallyDrop {{");
130 writeln!(out, " T value;");
131 writeln!(
132 out,
133 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
134 );
135 writeln!(out, " ~ManuallyDrop() {{}}");
136 writeln!(out, "}};");
137 }
138
139 if builtin.maybe_uninit {
140 out.next_section();
141 writeln!(out, "template <typename T>");
142 writeln!(out, "union MaybeUninit {{");
143 writeln!(out, " T value;");
144 writeln!(out, " MaybeUninit() {{}}");
145 writeln!(out, " ~MaybeUninit() {{}}");
146 writeln!(out, "}};");
147 }
148
David Tolnay0c033e32020-11-01 15:15:48 -0800149 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700150
David Tolnay919085c2020-10-31 22:32:22 -0700151 if builtin.ptr_len {
David Tolnay0c033e32020-11-01 15:15:48 -0800152 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700153 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800154 writeln!(out, " void *ptr;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700155 writeln!(out, " size_t len;");
156 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800157 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700158 }
159
160 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
161 out.next_section();
162 writeln!(out, "template <>");
163 writeln!(out, "class impl<Str> final {{");
164 writeln!(out, "public:");
165 if builtin.rust_str_new_unchecked {
166 writeln!(
167 out,
168 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
169 );
170 writeln!(out, " Str str;");
171 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
172 writeln!(out, " str.len = repr.len;");
173 writeln!(out, " return str;");
174 writeln!(out, " }}");
175 }
176 if builtin.rust_str_repr {
177 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800178 writeln!(
179 out,
180 " return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
181 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700182 writeln!(out, " }}");
183 }
184 writeln!(out, "}};");
185 }
186
David Tolnay36aa9e02020-10-31 23:08:21 -0700187 if builtin.rust_slice_new || builtin.rust_slice_repr {
188 out.next_section();
189 writeln!(out, "template <typename T>");
190 writeln!(out, "class impl<Slice<T>> final {{");
191 writeln!(out, "public:");
192 if builtin.rust_slice_new {
193 writeln!(
194 out,
195 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
196 );
David Tolnayc5629f02020-11-23 18:32:46 -0800197 writeln!(out, " return {{static_cast<T *>(repr.ptr), repr.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700198 writeln!(out, " }}");
199 }
200 if builtin.rust_slice_repr {
David Tolnayc5629f02020-11-23 18:32:46 -0800201 include.type_traits = true;
David Tolnay36aa9e02020-10-31 23:08:21 -0700202 writeln!(
203 out,
204 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
205 );
David Tolnayc5629f02020-11-23 18:32:46 -0800206 writeln!(out, " return repr::PtrLen{{");
207 writeln!(
208 out,
209 " const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
210 );
211 writeln!(out, " slice.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700212 writeln!(out, " }}");
213 }
214 writeln!(out, "}};");
215 }
216
David Tolnay3374d8d2020-10-31 22:18:45 -0700217 if builtin.rust_error {
218 out.next_section();
219 writeln!(out, "template <>");
220 writeln!(out, "class impl<Error> final {{");
221 writeln!(out, "public:");
222 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
223 writeln!(out, " Error error;");
224 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
225 writeln!(out, " error.len = repr.len;");
226 writeln!(out, " return error;");
227 writeln!(out, " }}");
228 writeln!(out, "}};");
229 }
230
David Tolnay53462762020-11-25 07:08:10 -0800231 if builtin.is_complete {
232 include.type_traits = true;
233 out.next_section();
234 writeln!(out, "template <typename T, typename = size_t>");
235 writeln!(out, "struct is_complete : std::false_type {{}};");
236 out.next_section();
237 writeln!(out, "template <typename T>");
238 writeln!(
239 out,
240 "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
241 );
242 }
243
244 if builtin.deleter_if {
245 out.next_section();
246 writeln!(out, "template <bool> struct deleter_if {{");
247 writeln!(out, " template <typename T> void operator()(T *) {{}}");
248 writeln!(out, "}};");
249 out.next_section();
250 writeln!(out, "template <> struct deleter_if<true> {{");
251 writeln!(
252 out,
253 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
254 );
255 writeln!(out, "}};");
256 }
257
David Tolnay0c033e32020-11-01 15:15:48 -0800258 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800259 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700260
261 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800262 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700263 include.exception = true;
264 include.type_traits = true;
265 include.utility = true;
266 writeln!(out, "class missing {{}};");
267 writeln!(out, "missing trycatch(...);");
268 writeln!(out);
269 writeln!(out, "template <typename Try, typename Fail>");
270 writeln!(out, "static typename ::std::enable_if<");
271 writeln!(
272 out,
273 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
274 );
275 writeln!(out, " missing>::value>::type");
276 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
277 writeln!(out, " func();");
278 writeln!(out, "}} catch (const ::std::exception &e) {{");
279 writeln!(out, " fail(e.what());");
280 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800281 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700282 }
283
David Tolnay0c033e32020-11-01 15:15:48 -0800284 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800285
286 if builtin.exception {
287 out.begin_block(Block::ExternC);
288 writeln!(
289 out,
David Tolnay0f0162f2020-11-16 23:43:37 -0800290 "const char *cxxbridge1$exception(const char *, size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800291 );
292 out.end_block(Block::ExternC);
293 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700294}