blob: 9c5f4fd781bb5e6af2c063bc4c6f4e467e9b62cf [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,
15 pub unsafe_bitcopy: bool,
16 pub rust_error: bool,
17 pub manually_drop: bool,
18 pub maybe_uninit: bool,
19 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070020 pub ptr_len: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070021 pub rust_str_new_unchecked: bool,
22 pub rust_str_repr: bool,
David Tolnay36aa9e02020-10-31 23:08:21 -070023 pub rust_slice_new: bool,
24 pub rust_slice_repr: bool,
David Tolnay1f010c62020-11-01 20:27:46 -080025 pub exception: bool,
David Tolnay174bd952020-11-02 09:23:12 -080026 pub relocatable: bool,
David Tolnay22664ae2020-11-04 16:30:45 -080027 pub friend_impl: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080028 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070029}
30
David Tolnay97c5b862020-11-01 14:59:01 -080031impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070032 pub fn new() -> Self {
33 Builtins::default()
34 }
35}
David Tolnay3374d8d2020-10-31 22:18:45 -070036
37pub(super) fn write(out: &mut OutFile) {
38 if out.builtin == Default::default() {
39 return;
40 }
41
42 let include = &mut out.include;
43 let builtin = &mut out.builtin;
44 let out = &mut builtin.content;
45
David Tolnaydcfa8e92020-11-02 09:50:06 -080046 if builtin.rust_string {
47 include.array = true;
48 include.cstdint = true;
49 include.string = true;
50 }
51
52 if builtin.rust_str {
53 include.cstdint = true;
54 include.string = true;
David Tolnay22664ae2020-11-04 16:30:45 -080055 builtin.friend_impl = true;
56 }
57
58 if builtin.rust_slice {
59 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080060 }
61
62 if builtin.rust_box {
63 include.new = true;
64 include.type_traits = true;
David Tolnayea6f86c2020-11-10 15:08:57 -080065 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080066 }
67
68 if builtin.rust_vec {
69 include.array = true;
70 include.new = true;
71 include.type_traits = true;
David Tolnayfb6b73c2020-11-10 14:32:16 -080072 include.utility = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080073 builtin.panic = true;
74 builtin.unsafe_bitcopy = true;
75 }
76
David Tolnaya5a13012020-11-10 15:03:09 -080077 if builtin.rust_fn {
78 include.utility = true;
79 }
80
David Tolnaydcfa8e92020-11-02 09:50:06 -080081 if builtin.rust_error {
82 include.exception = true;
David Tolnay22664ae2020-11-04 16:30:45 -080083 builtin.friend_impl = true;
David Tolnaydcfa8e92020-11-02 09:50:06 -080084 }
85
86 if builtin.rust_isize {
87 include.basetsd = true;
88 }
89
David Tolnay174bd952020-11-02 09:23:12 -080090 if builtin.relocatable {
91 include.type_traits = true;
92 }
93
David Tolnay0c033e32020-11-01 15:15:48 -080094 out.begin_block(Block::Namespace("rust"));
David Tolnay0f0162f2020-11-16 23:43:37 -080095 out.begin_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -070096 writeln!(out, "// #include \"rust/cxx.h\"");
97
David Tolnay0f0162f2020-11-16 23:43:37 -080098 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
David Tolnay3374d8d2020-10-31 22:18:45 -070099
100 if builtin.rust_string {
101 out.next_section();
102 writeln!(out, "struct unsafe_bitcopy_t;");
103 }
104
David Tolnay22664ae2020-11-04 16:30:45 -0800105 if builtin.friend_impl {
David Tolnay0c033e32020-11-01 15:15:48 -0800106 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700107 writeln!(out, "template <typename T>");
108 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -0800109 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700110 }
111
David Tolnay0f0162f2020-11-16 23:43:37 -0800112 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
113 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
114 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
115 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
116 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
117 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
118 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
119 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
120 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
121 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
David Tolnay3374d8d2020-10-31 22:18:45 -0700122
123 if builtin.manually_drop {
124 out.next_section();
125 include.utility = true;
126 writeln!(out, "template <typename T>");
127 writeln!(out, "union ManuallyDrop {{");
128 writeln!(out, " T value;");
129 writeln!(
130 out,
131 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
132 );
133 writeln!(out, " ~ManuallyDrop() {{}}");
134 writeln!(out, "}};");
135 }
136
137 if builtin.maybe_uninit {
138 out.next_section();
139 writeln!(out, "template <typename T>");
140 writeln!(out, "union MaybeUninit {{");
141 writeln!(out, " T value;");
142 writeln!(out, " MaybeUninit() {{}}");
143 writeln!(out, " ~MaybeUninit() {{}}");
144 writeln!(out, "}};");
145 }
146
David Tolnay0c033e32020-11-01 15:15:48 -0800147 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -0700148
David Tolnay919085c2020-10-31 22:32:22 -0700149 if builtin.ptr_len {
David Tolnay0c033e32020-11-01 15:15:48 -0800150 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700151 writeln!(out, "struct PtrLen final {{");
152 writeln!(out, " const void *ptr;");
153 writeln!(out, " size_t len;");
154 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800155 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700156 }
157
158 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
159 out.next_section();
160 writeln!(out, "template <>");
161 writeln!(out, "class impl<Str> final {{");
162 writeln!(out, "public:");
163 if builtin.rust_str_new_unchecked {
164 writeln!(
165 out,
166 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
167 );
168 writeln!(out, " Str str;");
169 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
170 writeln!(out, " str.len = repr.len;");
171 writeln!(out, " return str;");
172 writeln!(out, " }}");
173 }
174 if builtin.rust_str_repr {
175 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
176 writeln!(out, " return repr::PtrLen{{str.ptr, str.len}};");
177 writeln!(out, " }}");
178 }
179 writeln!(out, "}};");
180 }
181
David Tolnay36aa9e02020-10-31 23:08:21 -0700182 if builtin.rust_slice_new || builtin.rust_slice_repr {
183 out.next_section();
184 writeln!(out, "template <typename T>");
185 writeln!(out, "class impl<Slice<T>> final {{");
186 writeln!(out, "public:");
187 if builtin.rust_slice_new {
188 writeln!(
189 out,
190 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
191 );
192 writeln!(
193 out,
194 " return {{static_cast<const T *>(repr.ptr), repr.len}};",
195 );
196 writeln!(out, " }}");
197 }
198 if builtin.rust_slice_repr {
199 writeln!(
200 out,
201 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
202 );
203 writeln!(out, " return repr::PtrLen{{slice.ptr, slice.len}};");
204 writeln!(out, " }}");
205 }
206 writeln!(out, "}};");
207 }
208
David Tolnay3374d8d2020-10-31 22:18:45 -0700209 if builtin.rust_error {
210 out.next_section();
211 writeln!(out, "template <>");
212 writeln!(out, "class impl<Error> final {{");
213 writeln!(out, "public:");
214 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
215 writeln!(out, " Error error;");
216 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
217 writeln!(out, " error.len = repr.len;");
218 writeln!(out, " return error;");
219 writeln!(out, " }}");
220 writeln!(out, "}};");
221 }
222
David Tolnay0c033e32020-11-01 15:15:48 -0800223 out.end_block(Block::AnonymousNamespace);
David Tolnay0f0162f2020-11-16 23:43:37 -0800224 out.end_block(Block::InlineNamespace("cxxbridge1"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700225
226 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800227 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700228 include.exception = true;
229 include.type_traits = true;
230 include.utility = true;
231 writeln!(out, "class missing {{}};");
232 writeln!(out, "missing trycatch(...);");
233 writeln!(out);
234 writeln!(out, "template <typename Try, typename Fail>");
235 writeln!(out, "static typename ::std::enable_if<");
236 writeln!(
237 out,
238 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
239 );
240 writeln!(out, " missing>::value>::type");
241 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
242 writeln!(out, " func();");
243 writeln!(out, "}} catch (const ::std::exception &e) {{");
244 writeln!(out, " fail(e.what());");
245 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800246 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700247 }
248
David Tolnay0c033e32020-11-01 15:15:48 -0800249 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800250
251 if builtin.exception {
252 out.begin_block(Block::ExternC);
253 writeln!(
254 out,
David Tolnay0f0162f2020-11-16 23:43:37 -0800255 "const char *cxxbridge1$exception(const char *, size_t);",
David Tolnay1f010c62020-11-01 20:27:46 -0800256 );
257 out.end_block(Block::ExternC);
258 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700259}