cxx_build/gen/
builtin.rs

1use crate::gen::block::Block;
2use crate::gen::ifndef;
3use crate::gen::include::Includes;
4use crate::gen::out::{Content, OutFile};
5use crate::gen::pragma::Pragma;
6
7#[derive(#[automatically_derived]
impl<'a> ::core::default::Default for Builtins<'a> {
    #[inline]
    fn default() -> Builtins<'a> {
        Builtins {
            panic: ::core::default::Default::default(),
            rust_string: ::core::default::Default::default(),
            rust_str: ::core::default::Default::default(),
            rust_slice: ::core::default::Default::default(),
            rust_box: ::core::default::Default::default(),
            rust_vec: ::core::default::Default::default(),
            rust_fn: ::core::default::Default::default(),
            rust_isize: ::core::default::Default::default(),
            opaque: ::core::default::Default::default(),
            layout: ::core::default::Default::default(),
            unsafe_bitcopy: ::core::default::Default::default(),
            unsafe_bitcopy_t: ::core::default::Default::default(),
            rust_error: ::core::default::Default::default(),
            manually_drop: ::core::default::Default::default(),
            maybe_uninit: ::core::default::Default::default(),
            trycatch: ::core::default::Default::default(),
            ptr_len: ::core::default::Default::default(),
            repr_fat: ::core::default::Default::default(),
            rust_str_new_unchecked: ::core::default::Default::default(),
            rust_str_repr: ::core::default::Default::default(),
            rust_slice_new: ::core::default::Default::default(),
            rust_slice_repr: ::core::default::Default::default(),
            relocatable: ::core::default::Default::default(),
            relocatable_or_array: ::core::default::Default::default(),
            friend_impl: ::core::default::Default::default(),
            is_complete: ::core::default::Default::default(),
            destroy: ::core::default::Default::default(),
            deleter_if: ::core::default::Default::default(),
            shared_ptr: ::core::default::Default::default(),
            vector: ::core::default::Default::default(),
            alignmax: ::core::default::Default::default(),
            content: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for Builtins<'a> {
    #[inline]
    fn eq(&self, other: &Builtins<'a>) -> bool {
        self.panic == other.panic && self.rust_string == other.rust_string &&
                                                                                                                                self.rust_str == other.rust_str &&
                                                                                                                            self.rust_slice == other.rust_slice &&
                                                                                                                        self.rust_box == other.rust_box &&
                                                                                                                    self.rust_vec == other.rust_vec &&
                                                                                                                self.rust_fn == other.rust_fn &&
                                                                                                            self.rust_isize == other.rust_isize &&
                                                                                                        self.opaque == other.opaque && self.layout == other.layout
                                                                                                && self.unsafe_bitcopy == other.unsafe_bitcopy &&
                                                                                            self.unsafe_bitcopy_t == other.unsafe_bitcopy_t &&
                                                                                        self.rust_error == other.rust_error &&
                                                                                    self.manually_drop == other.manually_drop &&
                                                                                self.maybe_uninit == other.maybe_uninit &&
                                                                            self.trycatch == other.trycatch &&
                                                                        self.ptr_len == other.ptr_len &&
                                                                    self.repr_fat == other.repr_fat &&
                                                                self.rust_str_new_unchecked == other.rust_str_new_unchecked
                                                            && self.rust_str_repr == other.rust_str_repr &&
                                                        self.rust_slice_new == other.rust_slice_new &&
                                                    self.rust_slice_repr == other.rust_slice_repr &&
                                                self.relocatable == other.relocatable &&
                                            self.relocatable_or_array == other.relocatable_or_array &&
                                        self.friend_impl == other.friend_impl &&
                                    self.is_complete == other.is_complete &&
                                self.destroy == other.destroy &&
                            self.deleter_if == other.deleter_if &&
                        self.shared_ptr == other.shared_ptr &&
                    self.vector == other.vector &&
                self.alignmax == other.alignmax &&
            self.content == other.content
    }
}PartialEq)]
8pub(crate) struct Builtins<'a> {
9    pub panic: bool,
10    pub rust_string: bool,
11    pub rust_str: bool,
12    pub rust_slice: bool,
13    pub rust_box: bool,
14    pub rust_vec: bool,
15    pub rust_fn: bool,
16    pub rust_isize: bool,
17    pub opaque: bool,
18    pub layout: bool,
19    pub unsafe_bitcopy: bool,
20    pub unsafe_bitcopy_t: bool,
21    pub rust_error: bool,
22    pub manually_drop: bool,
23    pub maybe_uninit: bool,
24    pub trycatch: bool,
25    pub ptr_len: bool,
26    pub repr_fat: bool,
27    pub rust_str_new_unchecked: bool,
28    pub rust_str_repr: bool,
29    pub rust_slice_new: bool,
30    pub rust_slice_repr: bool,
31    pub relocatable: bool,
32    pub relocatable_or_array: bool,
33    pub friend_impl: bool,
34    pub is_complete: bool,
35    pub destroy: bool,
36    pub deleter_if: bool,
37    pub shared_ptr: bool,
38    pub vector: bool,
39    pub alignmax: bool,
40    pub content: Content<'a>,
41}
42
43impl<'a> Builtins<'a> {
44    pub(crate) fn new() -> Self {
45        Builtins::default()
46    }
47}
48
49pub(super) fn write(out: &mut OutFile) {
50    if out.builtin == Default::default() {
51        return;
52    }
53
54    let include = &mut out.include;
55    let pragma = &mut out.pragma;
56    let builtin = &mut out.builtin;
57    let out = &mut builtin.content;
58
59    if builtin.rust_string {
60        include.array = true;
61        include.cstdint = true;
62        include.string = true;
63    }
64
65    if builtin.rust_str {
66        include.array = true;
67        include.cstdint = true;
68        include.string = true;
69        include.string_view = true;
70        builtin.friend_impl = true;
71    }
72
73    if builtin.rust_vec {
74        include.algorithm = true;
75        include.array = true;
76        include.cassert = true;
77        include.cstddef = true;
78        include.cstdint = true;
79        include.initializer_list = true;
80        include.iterator = true;
81        include.new = true;
82        include.stdexcept = true;
83        include.type_traits = true;
84        include.utility = true;
85        builtin.panic = true;
86        builtin.rust_slice = true;
87        builtin.unsafe_bitcopy_t = true;
88    }
89
90    if builtin.rust_slice {
91        include.array = true;
92        include.cassert = true;
93        include.cstddef = true;
94        include.cstdint = true;
95        include.iterator = true;
96        include.ranges = true;
97        include.stdexcept = true;
98        include.type_traits = true;
99        builtin.friend_impl = true;
100        builtin.layout = true;
101        builtin.panic = true;
102    }
103
104    if builtin.rust_box {
105        include.new = true;
106        include.type_traits = true;
107        include.utility = true;
108    }
109
110    if builtin.rust_fn {
111        include.utility = true;
112    }
113
114    if builtin.rust_error {
115        include.exception = true;
116        builtin.friend_impl = true;
117    }
118
119    if builtin.rust_isize {
120        include.basetsd = true;
121        include.sys_types = true;
122    }
123
124    if builtin.relocatable_or_array {
125        include.cstddef = true;
126        builtin.relocatable = true;
127    }
128
129    if builtin.relocatable {
130        include.type_traits = true;
131    }
132
133    if builtin.layout {
134        include.type_traits = true;
135        include.cstddef = true;
136        builtin.is_complete = true;
137    }
138
139    if builtin.shared_ptr {
140        include.memory = true;
141        include.type_traits = true;
142        builtin.is_complete = true;
143    }
144
145    if builtin.is_complete {
146        include.cstddef = true;
147        include.type_traits = true;
148    }
149
150    if builtin.unsafe_bitcopy {
151        builtin.unsafe_bitcopy_t = true;
152    }
153
154    if builtin.trycatch {
155        builtin.ptr_len = true;
156    }
157
158    out.begin_block(Block::Namespace("rust"));
159    out.begin_block(Block::InlineNamespace("cxxbridge1"));
160
161    let cxx_header = include.has_cxx_header();
162    if !cxx_header {
163        out.write_fmt(format_args!("// #include \"rust/cxx.h\"\n"));writeln!(out, "// #include \"rust/cxx.h\"");
164
165        ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
166
167        if builtin.rust_string {
168            out.next_section();
169            out.write_fmt(format_args!("struct unsafe_bitcopy_t;\n"));writeln!(out, "struct unsafe_bitcopy_t;");
170        }
171
172        if builtin.friend_impl {
173            out.begin_block(Block::AnonymousNamespace);
174            out.write_fmt(format_args!("template <typename T>\n"));writeln!(out, "template <typename T>");
175            out.write_fmt(format_args!("class impl;\n"));writeln!(out, "class impl;");
176            out.end_block(Block::AnonymousNamespace);
177        }
178
179        out.next_section();
180        if builtin.rust_str && !builtin.rust_string {
181            out.write_fmt(format_args!("class String;\n"));writeln!(out, "class String;");
182        }
183        if builtin.layout && !builtin.opaque {
184            out.write_fmt(format_args!("class Opaque;\n"));writeln!(out, "class Opaque;");
185        }
186
187        if builtin.rust_slice {
188            out.next_section();
189            out.write_fmt(format_args!("template <typename T>\n"));writeln!(out, "template <typename T>");
190            out.write_fmt(format_args!("::std::size_t size_of();\n"));writeln!(out, "::std::size_t size_of();");
191            out.write_fmt(format_args!("template <typename T>\n"));writeln!(out, "template <typename T>");
192            out.write_fmt(format_args!("::std::size_t align_of();\n"));writeln!(out, "::std::size_t align_of();");
193        }
194
195        ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
196        ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
197        ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
198        ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
199        ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
200        ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
201        ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
202        ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
203        ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
204        ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
205        ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
206        ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
207        ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
208        ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
209    }
210
211    out.end_block(Block::InlineNamespace("cxxbridge1"));
212    out.end_block(Block::Namespace("rust"));
213
214    macro_rules! write_builtin {
215        ($path:literal) => {
216            write_builtin(out, include, pragma, include_str!($path));
217        };
218    }
219
220    // namespace rust::cxxbridge1
221
222    if builtin.rust_str_new_unchecked {
223        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\nclass Str::uninit {};\n//\ninline Str::Str(uninit) noexcept {}\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/rust_str_uninit.h");
224    }
225
226    if builtin.rust_slice_new {
227        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\ntemplate <typename T>\nclass Slice<T>::uninit {};\n//\ntemplate <typename T>\ninline Slice<T>::Slice(uninit) noexcept {}\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/rust_slice_uninit.h");
228    }
229
230    // namespace rust::cxxbridge1::repr
231
232    if builtin.repr_fat {
233        write_builtin(out, include, pragma,
    "#pragma once\n#include <array>\n#include <cstdint>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\nusing Fat = ::std::array<::std::uintptr_t, 2>;\n} // namespace repr\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/repr_fat.h");
234    }
235
236    if builtin.ptr_len {
237        write_builtin(out, include, pragma,
    "#pragma once\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\nstruct PtrLen final {\n  void *ptr;\n  ::std::size_t len;\n};\n} // namespace repr\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/ptr_len.h");
238    }
239
240    if builtin.alignmax {
241        write_builtin(out, include, pragma,
    "#pragma once\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace repr {\n#ifndef CXXBRIDGE_ALIGNMAX\n#define CXXBRIDGE_ALIGNMAX\n// This would be cleaner as the following, but GCC does not implement that\n// correctly. <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64236>\n//\n//     template <::std::size_t... N>\n//     class alignas(N...) alignmax {};\n//\n// Next, it could be this, but MSVC does not implement this correctly.\n//\n//     template <::std::size_t... N>\n//     class alignmax { alignas(N...) union {} members; };\n//\ntemplate <::std::size_t N>\nclass alignas(N) aligned {};\n//\ntemplate <typename... T>\nclass alignmax_t { alignas(T...) union {} members; };\n//\ntemplate <::std::size_t... N>\nusing alignmax = alignmax_t<aligned<N>...>;\n#endif // CXXBRIDGE_ALIGNMAX\n} // namespace repr\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/alignmax.h");
242    }
243
244    // namespace rust::cxxbridge1::detail
245
246    if builtin.maybe_uninit {
247        write_builtin(out, include, pragma,
    "#pragma once\n#include <cstddef>\n#include <new>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace detail {\ntemplate <typename T, typename = void *>\nstruct operator_new {\n  void *operator()(::std::size_t sz) { return ::operator new(sz); }\n};\n\ntemplate <typename T>\nstruct operator_new<T, decltype(T::operator new(sizeof(T)))> {\n  void *operator()(::std::size_t sz) { return T::operator new(sz); }\n};\n} // namespace detail\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/maybe_uninit_detail.h");
248    }
249
250    if builtin.trycatch {
251        write_builtin(out, include, pragma,
    "#pragma once\n#include \"./ptr_len.h\"\n#include <string>\n\n#pragma GCC diagnostic ignored \"-Wshadow\"\n#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace detail {\nclass Fail final {\n  ::rust::repr::PtrLen &throw$;\n  //\npublic:\n  Fail(::rust::repr::PtrLen &throw$) noexcept : throw$(throw$) {}\n  void operator()(char const *) noexcept;\n  void operator()(std::string const &) noexcept;\n};\n} // namespace detail\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/trycatch_detail.h");
252    }
253
254    // namespace rust::cxxbridge1
255
256    if builtin.manually_drop {
257        write_builtin(out, include, pragma,
    "#pragma once\n#include <utility>\n\n#pragma GCC diagnostic ignored \"-Wshadow\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\ntemplate <typename T>\nunion ManuallyDrop {\n  T value;\n  ManuallyDrop(T &&value) : value(::std::move(value)) {}\n  ~ManuallyDrop() {}\n};\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/manually_drop.h");
258    }
259
260    if builtin.maybe_uninit {
261        write_builtin(out, include, pragma,
    "#pragma once\n#include \"./maybe_uninit_detail.h\"\n#include <cstddef>\n\nnamespace rust {\ninline namespace cxxbridge1 {\ntemplate <typename T>\nunion MaybeUninit {\n  T value;\n  void *operator new(::std::size_t sz) { return detail::operator_new<T>{}(sz); }\n  MaybeUninit() {}\n  ~MaybeUninit() {}\n};\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/maybe_uninit.h");
262    }
263
264    out.begin_block(Block::Namespace("rust"));
265    out.begin_block(Block::InlineNamespace("cxxbridge1"));
266    out.begin_block(Block::AnonymousNamespace);
267
268    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
269        out.next_section();
270        out.write_fmt(format_args!("template <>\n"));writeln!(out, "template <>");
271        out.write_fmt(format_args!("class impl<Str> final {{\n"));writeln!(out, "class impl<Str> final {{");
272        out.write_fmt(format_args!("public:\n"));writeln!(out, "public:");
273        if builtin.rust_str_new_unchecked {
274            out.write_fmt(format_args!("  static Str new_unchecked(repr::Fat repr) noexcept {{\n"));writeln!(
275                out,
276                "  static Str new_unchecked(repr::Fat repr) noexcept {{",
277            );
278            out.write_fmt(format_args!("    Str str = Str::uninit{{}};\n"));writeln!(out, "    Str str = Str::uninit{{}};");
279            out.write_fmt(format_args!("    str.repr = repr;\n"));writeln!(out, "    str.repr = repr;");
280            out.write_fmt(format_args!("    return str;\n"));writeln!(out, "    return str;");
281            out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
282        }
283        if builtin.rust_str_repr {
284            out.write_fmt(format_args!("  static repr::Fat repr(Str str) noexcept {{\n"));writeln!(out, "  static repr::Fat repr(Str str) noexcept {{");
285            out.write_fmt(format_args!("    return str.repr;\n"));writeln!(out, "    return str.repr;");
286            out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
287        }
288        out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
289    }
290
291    if builtin.rust_slice_new || builtin.rust_slice_repr {
292        out.next_section();
293        out.write_fmt(format_args!("template <typename T>\n"));writeln!(out, "template <typename T>");
294        out.write_fmt(format_args!("class impl<Slice<T>> final {{\n"));writeln!(out, "class impl<Slice<T>> final {{");
295        out.write_fmt(format_args!("public:\n"));writeln!(out, "public:");
296        if builtin.rust_slice_new {
297            out.write_fmt(format_args!("  static Slice<T> slice(repr::Fat repr) noexcept {{\n"));writeln!(out, "  static Slice<T> slice(repr::Fat repr) noexcept {{");
298            out.write_fmt(format_args!("    Slice<T> slice = typename Slice<T>::uninit{{}};\n"));writeln!(out, "    Slice<T> slice = typename Slice<T>::uninit{{}};");
299            out.write_fmt(format_args!("    slice.repr = repr;\n"));writeln!(out, "    slice.repr = repr;");
300            out.write_fmt(format_args!("    return slice;\n"));writeln!(out, "    return slice;");
301            out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
302        }
303        if builtin.rust_slice_repr {
304            out.write_fmt(format_args!("  static repr::Fat repr(Slice<T> slice) noexcept {{\n"));writeln!(out, "  static repr::Fat repr(Slice<T> slice) noexcept {{");
305            out.write_fmt(format_args!("    return slice.repr;\n"));writeln!(out, "    return slice.repr;");
306            out.write_fmt(format_args!("  }}\n"));writeln!(out, "  }}");
307        }
308        out.write_fmt(format_args!("}};\n"));writeln!(out, "}};");
309    }
310
311    out.end_block(Block::AnonymousNamespace);
312    out.end_block(Block::InlineNamespace("cxxbridge1"));
313    out.end_block(Block::Namespace("rust"));
314
315    // namespace rust::cxxbridge1::(anonymous)
316
317    if builtin.rust_error {
318        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n#include \"./friend_impl.h\"\n#include \"./ptr_len.h\"\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <>\nclass impl<Error> final {\npublic:\n  static Error error(repr::PtrLen repr) noexcept {\n    Error error;\n    error.msg = static_cast<char const *>(repr.ptr);\n    error.len = repr.len;\n    return error;\n  }\n};\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/rust_error.h");
319    }
320
321    if builtin.destroy {
322        write_builtin(out, include, pragma,
    "#pragma once\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T>\nvoid destroy(T *ptr) {\n  ptr->~T();\n}\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/destroy.h");
323    }
324
325    if builtin.deleter_if {
326        write_builtin(out, include, pragma,
    "#pragma once\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <bool> struct deleter_if {\n  template <typename T> void operator()(T *) {}\n};\n//\ntemplate <> struct deleter_if<true> {\n  template <typename T> void operator()(T *ptr) { ptr->~T(); }\n};\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/deleter_if.h");
327    }
328
329    if builtin.shared_ptr {
330        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n#include <memory>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T, bool = ::rust::detail::is_complete<T>::value>\nstruct is_destructible : ::std::false_type {};\n//\ntemplate <typename T>\nstruct is_destructible<T, true> : ::std::is_destructible<T> {};\n//\ntemplate <typename T>\nstruct is_destructible<T[], false> : is_destructible<T> {};\n//\ntemplate <typename T, bool = ::rust::is_destructible<T>::value>\nstruct shared_ptr_if_destructible {\n  explicit shared_ptr_if_destructible(typename ::std::shared_ptr<T>::element_type *) {}\n};\n//\ntemplate <typename T>\nstruct shared_ptr_if_destructible<T, true> : ::std::shared_ptr<T> {\n  using ::std::shared_ptr<T>::shared_ptr;\n};\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/shared_ptr.h");
331    }
332
333    if builtin.vector {
334        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n#include <type_traits>\n#include <vector>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T, bool = ::std::is_move_constructible<T>::value>\nstruct if_move_constructible {\n  static bool reserve(::std::vector<T> &, ::std::size_t) noexcept {\n    return false;\n  }\n};\n//\ntemplate <typename T>\nstruct if_move_constructible<T, true> {\n  static bool reserve(::std::vector<T> &vec, ::std::size_t new_cap) {\n    vec.reserve(new_cap);\n    return true;\n  }\n};\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/vector.h");
335    }
336
337    if builtin.relocatable_or_array {
338        write_builtin(out, include, pragma,
    "#pragma once\n#include \"../../../include/cxx.h\"\n#include <cstdint>\n\nnamespace rust {\ninline namespace cxxbridge1 {\nnamespace {\ntemplate <typename T>\nstruct IsRelocatableOrArray : IsRelocatable<T> {};\n//\ntemplate <typename T, ::std::size_t N>\nstruct IsRelocatableOrArray<T[N]> : IsRelocatableOrArray<T> {};\n} // namespace\n} // namespace cxxbridge1\n} // namespace rust\n");write_builtin!("builtin/relocatable_or_array.h");
339    }
340
341    // namespace rust::behavior
342
343    if builtin.trycatch {
344        write_builtin(out, include, pragma,
    "#pragma once\n#include \"./trycatch_detail.h\"\n#include <exception>\n#include <type_traits>\n#include <utility>\n\nnamespace rust {\nnamespace behavior {\nclass missing {};\nmissing trycatch(...);\n\ntemplate <typename Try, typename Fail>\nstatic typename ::std::enable_if<::std::is_same<\n    decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),\n    missing>::value>::type\ntrycatch(Try &&func, Fail &&fail) noexcept try {\n  func();\n} catch (::std::exception const &e) {\n  fail(e.what());\n}\n} // namespace behavior\n} // namespace rust\n");write_builtin!("builtin/trycatch.h");
345    }
346}
347
348fn write_builtin<'a>(
349    out: &mut Content<'a>,
350    include: &mut Includes,
351    pragma: &mut Pragma<'a>,
352    src: &'a str,
353) {
354    let mut namespace = Vec::new();
355    let mut ready = false;
356
357    for line in src.lines() {
358        if line == "#pragma once" || line.starts_with("#include \".") {
359            continue;
360        } else if let Some(rest) = line.strip_prefix("#include <") {
361            let Includes {
362                custom: _,
363                algorithm,
364                array,
365                cassert,
366                cstddef,
367                cstdint,
368                cstring,
369                exception,
370                functional,
371                initializer_list,
372                iterator,
373                limits,
374                memory,
375                new,
376                ranges,
377                stdexcept,
378                string,
379                string_view,
380                type_traits,
381                utility,
382                vector,
383                basetsd: _,
384                sys_types: _,
385                content: _,
386            } = include;
387            match rest.strip_suffix(">").unwrap() {
388                "algorithm" => *algorithm = true,
389                "array" => *array = true,
390                "cassert" => *cassert = true,
391                "cstddef" => *cstddef = true,
392                "cstdint" => *cstdint = true,
393                "cstring" => *cstring = true,
394                "exception" => *exception = true,
395                "functional" => *functional = true,
396                "initializer_list" => *initializer_list = true,
397                "iterator" => *iterator = true,
398                "limits" => *limits = true,
399                "memory" => *memory = true,
400                "new" => *new = true,
401                "ranges" => *ranges = true,
402                "stdexcept" => *stdexcept = true,
403                "string" => *string = true,
404                "string_view" => *string_view = true,
405                "type_traits" => *type_traits = true,
406                "utility" => *utility = true,
407                "vector" => *vector = true,
408                _ => {
    ::core::panicking::panic_fmt(format_args!("not implemented: {0}",
            format_args!("{0}", line)));
}unimplemented!("{}", line),
409            }
410        } else if let Some(rest) = line.strip_prefix("#pragma GCC diagnostic ignored \"") {
411            let diagnostic = rest.strip_suffix('"').unwrap();
412            pragma.gnu_diagnostic_ignore.insert(diagnostic);
413            ready = false;
414        } else if let Some(rest) = line.strip_prefix("#pragma clang diagnostic ignored \"") {
415            let diagnostic = rest.strip_suffix('"').unwrap();
416            pragma.clang_diagnostic_ignore.insert(diagnostic);
417            ready = false;
418        } else if line == "namespace {" {
419            namespace.push(Block::AnonymousNamespace);
420            out.begin_block(Block::AnonymousNamespace);
421        } else if let Some(rest) = line.strip_prefix("namespace ") {
422            let name = rest.strip_suffix(" {").unwrap();
423            namespace.push(Block::Namespace(name));
424            out.begin_block(Block::Namespace(name));
425        } else if let Some(rest) = line.strip_prefix("inline namespace ") {
426            let name = rest.strip_suffix(" {").unwrap();
427            namespace.push(Block::InlineNamespace(name));
428            out.begin_block(Block::InlineNamespace(name));
429        } else if line.starts_with("} // namespace") {
430            out.end_block(namespace.pop().unwrap());
431        } else if line.is_empty() && !ready {
432            out.next_section();
433            ready = true;
434        } else if !line.trim_start_matches(' ').starts_with("//") {
435            if !ready { ::core::panicking::panic("assertion failed: ready") };assert!(ready);
436            out.write_fmt(format_args!("{0}\n", line));writeln!(out, "{}", line);
437        }
438    }
439
440    if !namespace.is_empty() {
    ::core::panicking::panic("assertion failed: namespace.is_empty()")
};assert!(namespace.is_empty());
441    if !ready { ::core::panicking::panic("assertion failed: ready") };assert!(ready);
442}
443
444#[cfg(test)]
445mod tests {
446    use crate::gen::include::Includes;
447    use crate::gen::out::Content;
448    use crate::gen::pragma::Pragma;
449    use std::fs;
450
451    #[test]
452    fn test_write_builtin() {
453        let mut builtin_src = Vec::new();
454
455        for entry in fs::read_dir("src/gen/builtin").unwrap() {
456            let path = entry.unwrap().path();
457            let src = fs::read_to_string(path).unwrap();
458            builtin_src.push(src);
459        }
460
461        assert_ne!(builtin_src.len(), 0);
462        builtin_src.sort();
463
464        let mut content = Content::new();
465        let mut include = Includes::new();
466        let mut pragma = Pragma::new();
467        for src in &builtin_src {
468            super::write_builtin(&mut content, &mut include, &mut pragma, src);
469        }
470    }
471}