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 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 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 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 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 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 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}