1 use crate::gen::block::Block;
2 use crate::gen::ifndef;
3 use crate::gen::out::{Content, OutFile};
4
5 #[derive(Default, PartialEq)]
6 pub struct Builtins<'a> {
7 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 opaque: bool,
16 pub layout: bool,
17 pub unsafe_bitcopy: bool,
18 pub unsafe_bitcopy_t: bool,
19 pub rust_error: bool,
20 pub manually_drop: bool,
21 pub maybe_uninit: bool,
22 pub trycatch: bool,
23 pub ptr_len: bool,
24 pub repr_fat: bool,
25 pub rust_str_new_unchecked: bool,
26 pub rust_str_repr: bool,
27 pub rust_slice_new: bool,
28 pub rust_slice_repr: bool,
29 pub exception: bool,
30 pub relocatable: bool,
31 pub friend_impl: bool,
32 pub is_complete: bool,
33 pub destroy: bool,
34 pub deleter_if: bool,
35 pub content: Content<'a>,
36 }
37
38 impl<'a> Builtins<'a> {
new() -> Self39 pub fn new() -> Self {
40 Builtins::default()
41 }
42 }
43
write(out: &mut OutFile)44 pub(super) fn write(out: &mut OutFile) {
45 if out.builtin == Default::default() {
46 return;
47 }
48
49 let include = &mut out.include;
50 let builtin = &mut out.builtin;
51 let out = &mut builtin.content;
52
53 if builtin.rust_string {
54 include.array = true;
55 include.cstdint = true;
56 include.string = true;
57 }
58
59 if builtin.rust_str {
60 include.array = true;
61 include.cstdint = true;
62 include.string = true;
63 builtin.friend_impl = true;
64 }
65
66 if builtin.rust_vec {
67 include.algorithm = true;
68 include.array = true;
69 include.cassert = true;
70 include.cstddef = true;
71 include.cstdint = true;
72 include.initializer_list = true;
73 include.iterator = true;
74 include.new = true;
75 include.stdexcept = true;
76 include.type_traits = true;
77 include.utility = true;
78 builtin.panic = true;
79 builtin.rust_slice = true;
80 builtin.unsafe_bitcopy_t = true;
81 }
82
83 if builtin.rust_slice {
84 include.array = true;
85 include.cassert = true;
86 include.cstddef = true;
87 include.cstdint = true;
88 include.iterator = true;
89 include.stdexcept = true;
90 include.type_traits = true;
91 builtin.friend_impl = true;
92 builtin.layout = true;
93 builtin.panic = true;
94 }
95
96 if builtin.rust_box {
97 include.new = true;
98 include.type_traits = true;
99 include.utility = true;
100 }
101
102 if builtin.rust_fn {
103 include.utility = true;
104 }
105
106 if builtin.rust_error {
107 include.exception = true;
108 builtin.friend_impl = true;
109 }
110
111 if builtin.rust_isize {
112 include.basetsd = true;
113 include.sys_types = true;
114 }
115
116 if builtin.relocatable {
117 include.type_traits = true;
118 }
119
120 if builtin.layout {
121 include.type_traits = true;
122 include.cstddef = true;
123 builtin.is_complete = true;
124 }
125
126 if builtin.is_complete {
127 include.cstddef = true;
128 include.type_traits = true;
129 }
130
131 if builtin.unsafe_bitcopy {
132 builtin.unsafe_bitcopy_t = true;
133 }
134
135 out.begin_block(Block::Namespace("rust"));
136 out.begin_block(Block::InlineNamespace("cxxbridge1"));
137
138 let cxx_header = include.has_cxx_header();
139 if !cxx_header {
140 writeln!(out, "// #include \"rust/cxx.h\"");
141
142 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
143
144 if builtin.rust_string {
145 out.next_section();
146 writeln!(out, "struct unsafe_bitcopy_t;");
147 }
148
149 if builtin.friend_impl {
150 out.begin_block(Block::AnonymousNamespace);
151 writeln!(out, "template <typename T>");
152 writeln!(out, "class impl;");
153 out.end_block(Block::AnonymousNamespace);
154 }
155
156 out.next_section();
157 if builtin.rust_str && !builtin.rust_string {
158 writeln!(out, "class String;");
159 }
160 if builtin.layout && !builtin.opaque {
161 writeln!(out, "class Opaque;");
162 }
163
164 if builtin.rust_slice {
165 out.next_section();
166 writeln!(out, "template <typename T>");
167 writeln!(out, "::std::size_t size_of();");
168 writeln!(out, "template <typename T>");
169 writeln!(out, "::std::size_t align_of();");
170 }
171
172 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
173 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
174 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
175 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
176 ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
177 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
178 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
179 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
180 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
181 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
182 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
183 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
184 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
185 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
186 }
187
188 if builtin.rust_str_new_unchecked {
189 out.next_section();
190 writeln!(out, "class Str::uninit {{}};");
191 writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
192 }
193
194 if builtin.rust_slice_new {
195 out.next_section();
196 writeln!(out, "template <typename T>");
197 writeln!(out, "class Slice<T>::uninit {{}};");
198 writeln!(out, "template <typename T>");
199 writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
200 }
201
202 out.begin_block(Block::Namespace("detail"));
203
204 if builtin.maybe_uninit {
205 include.cstddef = true;
206 include.new = true;
207 out.next_section();
208 writeln!(out, "template <typename T, typename = void *>");
209 writeln!(out, "struct operator_new {{");
210 writeln!(
211 out,
212 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
213 );
214 writeln!(out, "}};");
215 out.next_section();
216 writeln!(out, "template <typename T>");
217 writeln!(
218 out,
219 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
220 );
221 writeln!(
222 out,
223 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
224 );
225 writeln!(out, "}};");
226 }
227
228 out.end_block(Block::Namespace("detail"));
229
230 if builtin.manually_drop {
231 out.next_section();
232 include.utility = true;
233 writeln!(out, "template <typename T>");
234 writeln!(out, "union ManuallyDrop {{");
235 writeln!(out, " T value;");
236 writeln!(
237 out,
238 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
239 );
240 writeln!(out, " ~ManuallyDrop() {{}}");
241 writeln!(out, "}};");
242 }
243
244 if builtin.maybe_uninit {
245 include.cstddef = true;
246 out.next_section();
247 writeln!(out, "template <typename T>");
248 writeln!(out, "union MaybeUninit {{");
249 writeln!(out, " T value;");
250 writeln!(
251 out,
252 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
253 );
254 writeln!(out, " MaybeUninit() {{}}");
255 writeln!(out, " ~MaybeUninit() {{}}");
256 writeln!(out, "}};");
257 }
258
259 out.begin_block(Block::AnonymousNamespace);
260
261 if builtin.repr_fat {
262 include.array = true;
263 include.cstdint = true;
264 out.next_section();
265 out.begin_block(Block::Namespace("repr"));
266 writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
267 out.end_block(Block::Namespace("repr"));
268 }
269
270 if builtin.ptr_len {
271 include.cstddef = true;
272 out.next_section();
273 out.begin_block(Block::Namespace("repr"));
274 writeln!(out, "struct PtrLen final {{");
275 writeln!(out, " void *ptr;");
276 writeln!(out, " ::std::size_t len;");
277 writeln!(out, "}};");
278 out.end_block(Block::Namespace("repr"));
279 }
280
281 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
282 out.next_section();
283 writeln!(out, "template <>");
284 writeln!(out, "class impl<Str> final {{");
285 writeln!(out, "public:");
286 if builtin.rust_str_new_unchecked {
287 writeln!(
288 out,
289 " static Str new_unchecked(repr::Fat repr) noexcept {{",
290 );
291 writeln!(out, " Str str = Str::uninit{{}};");
292 writeln!(out, " str.repr = repr;");
293 writeln!(out, " return str;");
294 writeln!(out, " }}");
295 }
296 if builtin.rust_str_repr {
297 writeln!(out, " static repr::Fat repr(Str str) noexcept {{");
298 writeln!(out, " return str.repr;");
299 writeln!(out, " }}");
300 }
301 writeln!(out, "}};");
302 }
303
304 if builtin.rust_slice_new || builtin.rust_slice_repr {
305 out.next_section();
306 writeln!(out, "template <typename T>");
307 writeln!(out, "class impl<Slice<T>> final {{");
308 writeln!(out, "public:");
309 if builtin.rust_slice_new {
310 writeln!(out, " static Slice<T> slice(repr::Fat repr) noexcept {{");
311 writeln!(out, " Slice<T> slice = typename Slice<T>::uninit{{}};");
312 writeln!(out, " slice.repr = repr;");
313 writeln!(out, " return slice;");
314 writeln!(out, " }}");
315 }
316 if builtin.rust_slice_repr {
317 writeln!(out, " static repr::Fat repr(Slice<T> slice) noexcept {{");
318 writeln!(out, " return slice.repr;");
319 writeln!(out, " }}");
320 }
321 writeln!(out, "}};");
322 }
323
324 if builtin.rust_error {
325 out.next_section();
326 writeln!(out, "template <>");
327 writeln!(out, "class impl<Error> final {{");
328 writeln!(out, "public:");
329 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
330 writeln!(out, " Error error;");
331 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
332 writeln!(out, " error.len = repr.len;");
333 writeln!(out, " return error;");
334 writeln!(out, " }}");
335 writeln!(out, "}};");
336 }
337
338 if builtin.destroy {
339 out.next_section();
340 writeln!(out, "template <typename T>");
341 writeln!(out, "void destroy(T *ptr) {{");
342 writeln!(out, " ptr->~T();");
343 writeln!(out, "}}");
344 }
345
346 if builtin.deleter_if {
347 out.next_section();
348 writeln!(out, "template <bool> struct deleter_if {{");
349 writeln!(out, " template <typename T> void operator()(T *) {{}}");
350 writeln!(out, "}};");
351 out.next_section();
352 writeln!(out, "template <> struct deleter_if<true> {{");
353 writeln!(
354 out,
355 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
356 );
357 writeln!(out, "}};");
358 }
359
360 out.end_block(Block::AnonymousNamespace);
361 out.end_block(Block::InlineNamespace("cxxbridge1"));
362
363 if builtin.trycatch {
364 out.begin_block(Block::Namespace("behavior"));
365 include.exception = true;
366 include.type_traits = true;
367 include.utility = true;
368 writeln!(out, "class missing {{}};");
369 writeln!(out, "missing trycatch(...);");
370 writeln!(out);
371 writeln!(out, "template <typename Try, typename Fail>");
372 writeln!(out, "static typename ::std::enable_if<");
373 writeln!(
374 out,
375 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
376 );
377 writeln!(out, " missing>::value>::type");
378 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
379 writeln!(out, " func();");
380 writeln!(out, "}} catch (const ::std::exception &e) {{");
381 writeln!(out, " fail(e.what());");
382 writeln!(out, "}}");
383 out.end_block(Block::Namespace("behavior"));
384 }
385
386 out.end_block(Block::Namespace("rust"));
387
388 if builtin.exception {
389 include.cstddef = true;
390 out.begin_block(Block::ExternC);
391 writeln!(
392 out,
393 "const char *cxxbridge1$exception(const char *, ::std::size_t);",
394 );
395 out.end_block(Block::ExternC);
396 }
397 }
398