blob: 36e32f89c47b0e96747d7695ffbc17c8a65404ec [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 Tolnay97c5b862020-11-01 14:59:01 -080026 pub content: Content<'a>,
David Tolnay3be0e1f2020-10-31 20:53:00 -070027}
28
David Tolnay97c5b862020-11-01 14:59:01 -080029impl<'a> Builtins<'a> {
David Tolnay3be0e1f2020-10-31 20:53:00 -070030 pub fn new() -> Self {
31 Builtins::default()
32 }
33}
David Tolnay3374d8d2020-10-31 22:18:45 -070034
35pub(super) fn write(out: &mut OutFile) {
36 if out.builtin == Default::default() {
37 return;
38 }
39
40 let include = &mut out.include;
41 let builtin = &mut out.builtin;
42 let out = &mut builtin.content;
43
David Tolnay0c033e32020-11-01 15:15:48 -080044 out.begin_block(Block::Namespace("rust"));
45 out.begin_block(Block::InlineNamespace("cxxbridge05"));
David Tolnay3374d8d2020-10-31 22:18:45 -070046 writeln!(out, "// #include \"rust/cxx.h\"");
47
48 ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
49
50 if builtin.rust_string {
51 out.next_section();
52 writeln!(out, "struct unsafe_bitcopy_t;");
53 }
54
55 if builtin.rust_error {
David Tolnay0c033e32020-11-01 15:15:48 -080056 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -070057 writeln!(out, "template <typename T>");
58 writeln!(out, "class impl;");
David Tolnay0c033e32020-11-01 15:15:48 -080059 out.end_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -070060 }
61
62 ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
63 ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
64 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
65 ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
66 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
67 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
68 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
69 ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
70 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
71
72 if builtin.manually_drop {
73 out.next_section();
74 include.utility = true;
75 writeln!(out, "template <typename T>");
76 writeln!(out, "union ManuallyDrop {{");
77 writeln!(out, " T value;");
78 writeln!(
79 out,
80 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
81 );
82 writeln!(out, " ~ManuallyDrop() {{}}");
83 writeln!(out, "}};");
84 }
85
86 if builtin.maybe_uninit {
87 out.next_section();
88 writeln!(out, "template <typename T>");
89 writeln!(out, "union MaybeUninit {{");
90 writeln!(out, " T value;");
91 writeln!(out, " MaybeUninit() {{}}");
92 writeln!(out, " ~MaybeUninit() {{}}");
93 writeln!(out, "}};");
94 }
95
David Tolnay0c033e32020-11-01 15:15:48 -080096 out.begin_block(Block::AnonymousNamespace);
David Tolnay3374d8d2020-10-31 22:18:45 -070097
David Tolnay919085c2020-10-31 22:32:22 -070098 if builtin.ptr_len {
David Tolnay0c033e32020-11-01 15:15:48 -080099 out.begin_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700100 writeln!(out, "struct PtrLen final {{");
101 writeln!(out, " const void *ptr;");
102 writeln!(out, " size_t len;");
103 writeln!(out, "}};");
David Tolnay0c033e32020-11-01 15:15:48 -0800104 out.end_block(Block::Namespace("repr"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700105 }
106
107 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
108 out.next_section();
109 writeln!(out, "template <>");
110 writeln!(out, "class impl<Str> final {{");
111 writeln!(out, "public:");
112 if builtin.rust_str_new_unchecked {
113 writeln!(
114 out,
115 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
116 );
117 writeln!(out, " Str str;");
118 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
119 writeln!(out, " str.len = repr.len;");
120 writeln!(out, " return str;");
121 writeln!(out, " }}");
122 }
123 if builtin.rust_str_repr {
124 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
125 writeln!(out, " return repr::PtrLen{{str.ptr, str.len}};");
126 writeln!(out, " }}");
127 }
128 writeln!(out, "}};");
129 }
130
David Tolnay36aa9e02020-10-31 23:08:21 -0700131 if builtin.rust_slice_new || builtin.rust_slice_repr {
132 out.next_section();
133 writeln!(out, "template <typename T>");
134 writeln!(out, "class impl<Slice<T>> final {{");
135 writeln!(out, "public:");
136 if builtin.rust_slice_new {
137 writeln!(
138 out,
139 " static Slice<T> slice(repr::PtrLen repr) noexcept {{",
140 );
141 writeln!(
142 out,
143 " return {{static_cast<const T *>(repr.ptr), repr.len}};",
144 );
145 writeln!(out, " }}");
146 }
147 if builtin.rust_slice_repr {
148 writeln!(
149 out,
150 " static repr::PtrLen repr(Slice<T> slice) noexcept {{",
151 );
152 writeln!(out, " return repr::PtrLen{{slice.ptr, slice.len}};");
153 writeln!(out, " }}");
154 }
155 writeln!(out, "}};");
156 }
157
David Tolnay3374d8d2020-10-31 22:18:45 -0700158 if builtin.rust_error {
159 out.next_section();
160 writeln!(out, "template <>");
161 writeln!(out, "class impl<Error> final {{");
162 writeln!(out, "public:");
163 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
164 writeln!(out, " Error error;");
165 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
166 writeln!(out, " error.len = repr.len;");
167 writeln!(out, " return error;");
168 writeln!(out, " }}");
169 writeln!(out, "}};");
170 }
171
David Tolnay0c033e32020-11-01 15:15:48 -0800172 out.end_block(Block::AnonymousNamespace);
173 out.end_block(Block::InlineNamespace("cxxbridge05"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700174
175 if builtin.trycatch {
David Tolnay0c033e32020-11-01 15:15:48 -0800176 out.begin_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700177 include.exception = true;
178 include.type_traits = true;
179 include.utility = true;
180 writeln!(out, "class missing {{}};");
181 writeln!(out, "missing trycatch(...);");
182 writeln!(out);
183 writeln!(out, "template <typename Try, typename Fail>");
184 writeln!(out, "static typename ::std::enable_if<");
185 writeln!(
186 out,
187 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
188 );
189 writeln!(out, " missing>::value>::type");
190 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
191 writeln!(out, " func();");
192 writeln!(out, "}} catch (const ::std::exception &e) {{");
193 writeln!(out, " fail(e.what());");
194 writeln!(out, "}}");
David Tolnay0c033e32020-11-01 15:15:48 -0800195 out.end_block(Block::Namespace("behavior"));
David Tolnay3374d8d2020-10-31 22:18:45 -0700196 }
197
David Tolnay0c033e32020-11-01 15:15:48 -0800198 out.end_block(Block::Namespace("rust"));
David Tolnay1f010c62020-11-01 20:27:46 -0800199
200 if builtin.exception {
201 out.begin_block(Block::ExternC);
202 writeln!(
203 out,
204 "const char *cxxbridge05$exception(const char *, size_t);",
205 );
206 out.end_block(Block::ExternC);
207 }
David Tolnay3374d8d2020-10-31 22:18:45 -0700208}