• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 relocatable: bool,
30     pub relocatable_or_array: 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_or_array {
117         include.cstddef = true;
118         builtin.relocatable = true;
119     }
120 
121     if builtin.relocatable {
122         include.type_traits = true;
123     }
124 
125     if builtin.layout {
126         include.type_traits = true;
127         include.cstddef = true;
128         builtin.is_complete = true;
129     }
130 
131     if builtin.is_complete {
132         include.cstddef = true;
133         include.type_traits = true;
134     }
135 
136     if builtin.unsafe_bitcopy {
137         builtin.unsafe_bitcopy_t = true;
138     }
139 
140     if builtin.trycatch {
141         builtin.ptr_len = true;
142     }
143 
144     out.begin_block(Block::Namespace("rust"));
145     out.begin_block(Block::InlineNamespace("cxxbridge1"));
146 
147     let cxx_header = include.has_cxx_header();
148     if !cxx_header {
149         writeln!(out, "// #include \"rust/cxx.h\"");
150 
151         ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
152 
153         if builtin.rust_string {
154             out.next_section();
155             writeln!(out, "struct unsafe_bitcopy_t;");
156         }
157 
158         if builtin.friend_impl {
159             out.begin_block(Block::AnonymousNamespace);
160             writeln!(out, "template <typename T>");
161             writeln!(out, "class impl;");
162             out.end_block(Block::AnonymousNamespace);
163         }
164 
165         out.next_section();
166         if builtin.rust_str && !builtin.rust_string {
167             writeln!(out, "class String;");
168         }
169         if builtin.layout && !builtin.opaque {
170             writeln!(out, "class Opaque;");
171         }
172 
173         if builtin.rust_slice {
174             out.next_section();
175             writeln!(out, "template <typename T>");
176             writeln!(out, "::std::size_t size_of();");
177             writeln!(out, "template <typename T>");
178             writeln!(out, "::std::size_t align_of();");
179         }
180 
181         ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
182         ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
183         ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
184         ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
185         ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
186         ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
187         ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
188         ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
189         ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
190         ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
191         ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
192         ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
193         ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
194         ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
195     }
196 
197     if builtin.rust_str_new_unchecked {
198         out.next_section();
199         writeln!(out, "class Str::uninit {{}};");
200         writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
201     }
202 
203     if builtin.rust_slice_new {
204         out.next_section();
205         writeln!(out, "template <typename T>");
206         writeln!(out, "class Slice<T>::uninit {{}};");
207         writeln!(out, "template <typename T>");
208         writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
209     }
210 
211     out.begin_block(Block::Namespace("repr"));
212 
213     if builtin.repr_fat {
214         include.array = true;
215         include.cstdint = true;
216         out.next_section();
217         writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
218     }
219 
220     if builtin.ptr_len {
221         include.cstddef = true;
222         out.next_section();
223         writeln!(out, "struct PtrLen final {{");
224         writeln!(out, "  void *ptr;");
225         writeln!(out, "  ::std::size_t len;");
226         writeln!(out, "}};");
227     }
228 
229     out.end_block(Block::Namespace("repr"));
230 
231     out.begin_block(Block::Namespace("detail"));
232 
233     if builtin.maybe_uninit {
234         include.cstddef = true;
235         include.new = true;
236         out.next_section();
237         writeln!(out, "template <typename T, typename = void *>");
238         writeln!(out, "struct operator_new {{");
239         writeln!(
240             out,
241             "  void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
242         );
243         writeln!(out, "}};");
244         out.next_section();
245         writeln!(out, "template <typename T>");
246         writeln!(
247             out,
248             "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
249         );
250         writeln!(
251             out,
252             "  void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
253         );
254         writeln!(out, "}};");
255     }
256 
257     if builtin.trycatch {
258         include.string = true;
259         out.next_section();
260         writeln!(out, "class Fail final {{");
261         writeln!(out, "  ::rust::repr::PtrLen &throw$;");
262         writeln!(out, "public:");
263         writeln!(
264             out,
265             "  Fail(::rust::repr::PtrLen &throw$) noexcept : throw$(throw$) {{}}",
266         );
267         writeln!(out, "  void operator()(char const *) noexcept;");
268         writeln!(out, "  void operator()(std::string const &) noexcept;");
269         writeln!(out, "}};");
270     }
271 
272     out.end_block(Block::Namespace("detail"));
273 
274     if builtin.manually_drop {
275         out.next_section();
276         include.utility = true;
277         writeln!(out, "template <typename T>");
278         writeln!(out, "union ManuallyDrop {{");
279         writeln!(out, "  T value;");
280         writeln!(
281             out,
282             "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
283         );
284         writeln!(out, "  ~ManuallyDrop() {{}}");
285         writeln!(out, "}};");
286     }
287 
288     if builtin.maybe_uninit {
289         include.cstddef = true;
290         out.next_section();
291         writeln!(out, "template <typename T>");
292         writeln!(out, "union MaybeUninit {{");
293         writeln!(out, "  T value;");
294         writeln!(
295             out,
296             "  void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
297         );
298         writeln!(out, "  MaybeUninit() {{}}");
299         writeln!(out, "  ~MaybeUninit() {{}}");
300         writeln!(out, "}};");
301     }
302 
303     out.begin_block(Block::AnonymousNamespace);
304 
305     if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
306         out.next_section();
307         writeln!(out, "template <>");
308         writeln!(out, "class impl<Str> final {{");
309         writeln!(out, "public:");
310         if builtin.rust_str_new_unchecked {
311             writeln!(
312                 out,
313                 "  static Str new_unchecked(repr::Fat repr) noexcept {{",
314             );
315             writeln!(out, "    Str str = Str::uninit{{}};");
316             writeln!(out, "    str.repr = repr;");
317             writeln!(out, "    return str;");
318             writeln!(out, "  }}");
319         }
320         if builtin.rust_str_repr {
321             writeln!(out, "  static repr::Fat repr(Str str) noexcept {{");
322             writeln!(out, "    return str.repr;");
323             writeln!(out, "  }}");
324         }
325         writeln!(out, "}};");
326     }
327 
328     if builtin.rust_slice_new || builtin.rust_slice_repr {
329         out.next_section();
330         writeln!(out, "template <typename T>");
331         writeln!(out, "class impl<Slice<T>> final {{");
332         writeln!(out, "public:");
333         if builtin.rust_slice_new {
334             writeln!(out, "  static Slice<T> slice(repr::Fat repr) noexcept {{");
335             writeln!(out, "    Slice<T> slice = typename Slice<T>::uninit{{}};");
336             writeln!(out, "    slice.repr = repr;");
337             writeln!(out, "    return slice;");
338             writeln!(out, "  }}");
339         }
340         if builtin.rust_slice_repr {
341             writeln!(out, "  static repr::Fat repr(Slice<T> slice) noexcept {{");
342             writeln!(out, "    return slice.repr;");
343             writeln!(out, "  }}");
344         }
345         writeln!(out, "}};");
346     }
347 
348     if builtin.rust_error {
349         out.next_section();
350         writeln!(out, "template <>");
351         writeln!(out, "class impl<Error> final {{");
352         writeln!(out, "public:");
353         writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
354         writeln!(out, "    Error error;");
355         writeln!(out, "    error.msg = static_cast<char const *>(repr.ptr);");
356         writeln!(out, "    error.len = repr.len;");
357         writeln!(out, "    return error;");
358         writeln!(out, "  }}");
359         writeln!(out, "}};");
360     }
361 
362     if builtin.destroy {
363         out.next_section();
364         writeln!(out, "template <typename T>");
365         writeln!(out, "void destroy(T *ptr) {{");
366         writeln!(out, "  ptr->~T();");
367         writeln!(out, "}}");
368     }
369 
370     if builtin.deleter_if {
371         out.next_section();
372         writeln!(out, "template <bool> struct deleter_if {{");
373         writeln!(out, "  template <typename T> void operator()(T *) {{}}");
374         writeln!(out, "}};");
375         out.next_section();
376         writeln!(out, "template <> struct deleter_if<true> {{");
377         writeln!(
378             out,
379             "  template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
380         );
381         writeln!(out, "}};");
382     }
383 
384     if builtin.relocatable_or_array {
385         out.next_section();
386         writeln!(out, "template <typename T>");
387         writeln!(out, "struct IsRelocatableOrArray : IsRelocatable<T> {{}};");
388         writeln!(out, "template <typename T, ::std::size_t N>");
389         writeln!(
390             out,
391             "struct IsRelocatableOrArray<T[N]> : IsRelocatableOrArray<T> {{}};",
392         );
393     }
394 
395     out.end_block(Block::AnonymousNamespace);
396     out.end_block(Block::InlineNamespace("cxxbridge1"));
397 
398     if builtin.trycatch {
399         out.begin_block(Block::Namespace("behavior"));
400         include.exception = true;
401         include.type_traits = true;
402         include.utility = true;
403         writeln!(out, "class missing {{}};");
404         writeln!(out, "missing trycatch(...);");
405         writeln!(out);
406         writeln!(out, "template <typename Try, typename Fail>");
407         writeln!(out, "static typename ::std::enable_if<");
408         writeln!(
409             out,
410             "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
411         );
412         writeln!(out, "                 missing>::value>::type");
413         writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
414         writeln!(out, "  func();");
415         writeln!(out, "}} catch (::std::exception const &e) {{");
416         writeln!(out, "  fail(e.what());");
417         writeln!(out, "}}");
418         out.end_block(Block::Namespace("behavior"));
419     }
420 
421     out.end_block(Block::Namespace("rust"));
422 }
423