blob: 621d88cf9a4d48d113f00a03b61367de9095e5bf [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,
David Tolnay365fc7c2020-11-25 16:08:13 -080015 pub opaque: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070016 pub unsafe_bitcopy: bool,
17 pub rust_error: bool,
18 pub manually_drop: bool,
19 pub maybe_uninit: bool,
20 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070021 pub ptr_len: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070022 pub rust_str_new_unchecked: bool,
23 pub rust_str_repr: bool,
David Tolnay36aa9e02020-10-31 23:08:21 -070024 pub rust_slice_new: bool,
25 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080026 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080027 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080028 pub friend_impl: bool,
David Tolnay53462762020-11-25 07:08:10 -080029 pub is_complete: bool,
30 pub deleter_if: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080031 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070032}
33
David Tolnay97c5b862020-11-01 14:59:01 -080034impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070035 pub fn new() -> Self {
36 Builtins::default()
37 }
38}
David Tolnay3374d8d2020-10-31 22:18:45 -070039
40pub(super) fn write(out: &mut OutFile) {
41 if out.builtin == Default::default() {
42 return;
43 }
44
45 let include = &mut out.include;
46 let builtin = &mut out.builtin;
47 let out = &mut builtin.content;
48
David Tolnaydcfa8e92020-11-02 09:50:06 -080049 if builtin.rust_string {
50 include.array = true;
51 include.cstdint = true;
52 include.string = true;
53 }
54
55 if builtin.rust_str {
56 include.cstdint = true;
57 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080058 builtin.friend_impl = true;
59 }
60
61 if builtin.rust_slice {
62 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080063 }
64
65 if builtin.rust_box {
66 include.new = true;
67 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080068 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080069 }
70
71 if builtin.rust_vec {
72 include.array = true;
73 include.new = true;
74 include.type_traits = true;
David Tolnayfb6b73c2020-11-10 14:32:16 -080075 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080076 builtin.panic = true;
77 builtin.unsafe_bitcopy = true;
78 }
79
David Tolnaya5a13012020-11-10 15:03:09 -080080 if builtin.rust_fn {
81 include.utility = true;
82 }
83
David Tolnaydcfa8e92020-11-02 09:50:06 -080084 if builtin.rust_error {
85 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080086 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080087 }
88
89 if builtin.rust_isize {
90 include.basetsd = true;
91 }
92
David Tolnay174bd952020-11-02 09:23:12 -080093 if builtin.relocatable {
94 include.type_traits = true;
95 }
96
David Tolnay0c033e32020-11-01 15:15:48 -080097 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -080098 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -070099 writeln!(out, "// #include \"rust/cxx.h\"");
100
David Tolnay0f0162f2020-11-16 23:43:37 -0800101 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -0700102
103 if builtin.rust_string {
104 out.next_section();
105 writeln!(out, "struct unsafe_bitcopy_t;");
106 }
107
David Tolnay22664ae2020-11-04 16:30:45 -0800108 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800109 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700110 writeln!(out, "template <typename T>");
111 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800112 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700113 }
114
David Tolnay0f0162f2020-11-16 23:43:37 -0800115 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
116 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
117 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
118 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
119 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
120 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
121 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
122 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
123 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
David Tolnay365fc7c2020-11-25 16:08:13 -0800124 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
David Tolnay0f0162f2020-11-16 23:43:37 -0800125 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700126
127 if builtin.manually_drop {
128 out.next_section();
129 include.utility = true;
130 writeln!(out, "template <typename T>");
131 writeln!(out, "union ManuallyDrop {{");
132 writeln!(out, " T value;");
133 writeln!(
134 out,
135 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
136 );
137 writeln!(out, " ~ManuallyDrop() {{}}");
138 writeln!(out, "}};");
139 }
140
141 if builtin.maybe_uninit {
142 out.next_section();
143 writeln!(out, "template <typename T>");
144 writeln!(out, "union MaybeUninit {{");
145 writeln!(out, " T value;");
146 writeln!(out, " MaybeUninit() {{}}");
147 writeln!(out, " ~MaybeUninit() {{}}");
148 writeln!(out, "}};");
149 }
150
David Tolnay0c033e32020-11-01 15:15:48 -0800151 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700152
David Tolnay919085c2020-10-31 22:32:22 -0700153 if builtin.ptr_len {
David Tolnay0c033e32020-11-01 15:15:48 -0800154 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700155 writeln!(out, "struct PtrLen final {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800156 writeln!(out, " void *ptr;");
David Tolnay3374d8d2020-10-31 22:18:45 -0700157 writeln!(out, " size_t len;");
158 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800159 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700160 }
161
162 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
163 out.next_section();
164 writeln!(out, "template <>");
165 writeln!(out, "class impl<Str> final {{");
166 writeln!(out, "public:");
167 if builtin.rust_str_new_unchecked {
168 writeln!(
169 out,
170 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
171 );
172 writeln!(out, " Str str;");
173 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
174 writeln!(out, " str.len = repr.len;");
175 writeln!(out, " return str;");
176 writeln!(out, " }}");
177 }
178 if builtin.rust_str_repr {
179 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
David Tolnayc5629f02020-11-23 18:32:46 -0800180 writeln!(
181 out,
182 " return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
183 );
David Tolnay3374d8d2020-10-31 22:18:45 -0700184 writeln!(out, " }}");
185 }
186 writeln!(out, "}};");
187 }
188
David Tolnay36aa9e02020-10-31 23:08:21 -0700189 if builtin.rust_slice_new || builtin.rust_slice_repr {
190 out.next_section();
191 writeln!(out, "template <typename T>");
192 writeln!(out, "class impl<Slice<T>> final {{");
193 writeln!(out, "public:");
194 if builtin.rust_slice_new {
195 writeln!(
196 out,
197 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
198 );
David Tolnayc5629f02020-11-23 18:32:46 -0800199 writeln!(out, " return {{static_cast<T *>(repr.ptr), repr.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700200 writeln!(out, " }}");
201 }
202 if builtin.rust_slice_repr {
David Tolnayc5629f02020-11-23 18:32:46 -0800203 include.type_traits = true;
David Tolnay36aa9e02020-10-31 23:08:21 -0700204 writeln!(
205 out,
206 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
207 );
David Tolnayc5629f02020-11-23 18:32:46 -0800208 writeln!(out, " return repr::PtrLen{{");
209 writeln!(
210 out,
211 " const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
212 );
213 writeln!(out, " slice.len}};");
David Tolnay36aa9e02020-10-31 23:08:21 -0700214 writeln!(out, " }}");
215 }
216 writeln!(out, "}};");
217 }
218
David Tolnay3374d8d2020-10-31 22:18:45 -0700219 if builtin.rust_error {
220 out.next_section();
221 writeln!(out, "template <>");
222 writeln!(out, "class impl<Error> final {{");
223 writeln!(out, "public:");
224 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
225 writeln!(out, " Error error;");
226 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
227 writeln!(out, " error.len = repr.len;");
228 writeln!(out, " return error;");
229 writeln!(out, " }}");
230 writeln!(out, "}};");
231 }
232
David Tolnay53462762020-11-25 07:08:10 -0800233 if builtin.is_complete {
234 include.type_traits = true;
235 out.next_section();
236 writeln!(out, "template <typename T, typename = size_t>");
237 writeln!(out, "struct is_complete : std::false_type {{}};");
238 out.next_section();
239 writeln!(out, "template <typename T>");
240 writeln!(
241 out,
242 "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
243 );
244 }
245
246 if builtin.deleter_if {
247 out.next_section();
248 writeln!(out, "template <bool> struct deleter_if {{");
249 writeln!(out, " template <typename T> void operator()(T *) {{}}");
250 writeln!(out, "}};");
251 out.next_section();
252 writeln!(out, "template <> struct deleter_if<true> {{");
253 writeln!(
254 out,
255 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
256 );
257 writeln!(out, "}};");
258 }
259
David Tolnay0c033e32020-11-01 15:15:48 -0800260 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800261 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700262
263 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800264 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700265 include.exception = true;
266 include.type_traits = true;
267 include.utility = true;
268 writeln!(out, "class missing {{}};");
269 writeln!(out, "missing trycatch(...);");
270 writeln!(out);
271 writeln!(out, "template <typename Try, typename Fail>");
272 writeln!(out, "static typename ::std::enable_if<");
273 writeln!(
274 out,
275 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
276 );
277 writeln!(out, " missing>::value>::type");
278 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
279 writeln!(out, " func();");
280 writeln!(out, "}} catch (const ::std::exception &e) {{");
281 writeln!(out, " fail(e.what());");
282 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800283 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700284 }
285
David Tolnay0c033e32020-11-01 15:15:48 -0800286 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800287
288 if builtin.exception {
289 out.begin_block(Block::ExternC);
290 writeln!(
291 out,
David Tolnay0f0162f2020-11-16 23:43:37 -0800292 "const char *cxxbridge1$exception(const char *, size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800293 );
294 out.end_block(Block::ExternC);
295 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700296}