1 use crate::gen::block::Block; 2 use crate::gen::ifndef; 3 use crate::gen::out::{Content, OutFile}; 4 5 #[derive(Default, PartialEq)] 6 pub struct Builtins<'a> { 7 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 opaque: bool, 16 pub layout: bool, 17 pub unsafe_bitcopy: bool, 18 pub unsafe_bitcopy_t: bool, 19 pub rust_error: bool, 20 pub manually_drop: bool, 21 pub maybe_uninit: bool, 22 pub trycatch: bool, 23 pub ptr_len: bool, 24 pub repr_fat: bool, 25 pub rust_str_new_unchecked: bool, 26 pub rust_str_repr: bool, 27 pub rust_slice_new: bool, 28 pub rust_slice_repr: bool, 29 pub relocatable: bool, 30 pub relocatable_or_array: bool, 31 pub friend_impl: bool, 32 pub is_complete: bool, 33 pub destroy: bool, 34 pub deleter_if: bool, 35 pub content: Content<'a>, 36 } 37 38 impl<'a> Builtins<'a> { newnull39 pub fn new() -> Self { 40 Builtins::default() 41 } 42 } 43 44 pub(super) fn write(out: &mut OutFile) { 45 if out.builtin == Default::default() { 46 return; 47 } 48 49 let include = &mut out.include; 50 let builtin = &mut out.builtin; 51 let out = &mut builtin.content; 52 53 if builtin.rust_string { 54 include.array = true; 55 include.cstdint = true; 56 include.string = true; 57 } 58 59 if builtin.rust_str { 60 include.array = true; 61 include.cstdint = true; 62 include.string = true; 63 builtin.friend_impl = true; 64 } 65 66 if builtin.rust_vec { 67 include.algorithm = true; 68 include.array = true; 69 include.cassert = true; 70 include.cstddef = true; 71 include.cstdint = true; 72 include.initializer_list = true; 73 include.iterator = true; 74 include.new = true; 75 include.stdexcept = true; 76 include.type_traits = true; 77 include.utility = true; 78 builtin.panic = true; 79 builtin.rust_slice = true; 80 builtin.unsafe_bitcopy_t = true; 81 } 82 83 if builtin.rust_slice { 84 include.array = true; 85 include.cassert = true; 86 include.cstddef = true; 87 include.cstdint = true; 88 include.iterator = true; 89 include.stdexcept = true; 90 include.type_traits = true; 91 builtin.friend_impl = true; 92 builtin.layout = true; 93 builtin.panic = true; 94 } 95 96 if builtin.rust_box { 97 include.new = true; 98 include.type_traits = true; 99 include.utility = true; 100 } 101 102 if builtin.rust_fn { 103 include.utility = true; 104 } 105 106 if builtin.rust_error { 107 include.exception = true; 108 builtin.friend_impl = true; 109 } 110 111 if builtin.rust_isize { 112 include.basetsd = true; 113 include.sys_types = true; 114 } 115 116 if builtin.relocatable_or_array { 117 include.cstddef = true; 118 builtin.relocatable = true; 119 } 120 121 if builtin.relocatable { 122 include.type_traits = true; 123 } 124 125 if builtin.layout { 126 include.type_traits = true; 127 include.cstddef = true; 128 builtin.is_complete = true; 129 } 130 131 if builtin.is_complete { 132 include.cstddef = true; 133 include.type_traits = true; 134 } 135 136 if builtin.unsafe_bitcopy { 137 builtin.unsafe_bitcopy_t = true; 138 } 139 140 if builtin.trycatch { 141 builtin.ptr_len = true; 142 } 143 144 out.begin_block(Block::Namespace("rust")); 145 out.begin_block(Block::InlineNamespace("cxxbridge1")); 146 147 let cxx_header = include.has_cxx_header(); 148 if !cxx_header { 149 writeln!(out, "// #include \"rust/cxx.h\""); 150 151 ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC"); 152 153 if builtin.rust_string { 154 out.next_section(); 155 writeln!(out, "struct unsafe_bitcopy_t;"); 156 } 157 158 if builtin.friend_impl { 159 out.begin_block(Block::AnonymousNamespace); 160 writeln!(out, "template <typename T>"); 161 writeln!(out, "class impl;"); 162 out.end_block(Block::AnonymousNamespace); 163 } 164 165 out.next_section(); 166 if builtin.rust_str && !builtin.rust_string { 167 writeln!(out, "class String;"); 168 } 169 if builtin.layout && !builtin.opaque { 170 writeln!(out, "class Opaque;"); 171 } 172 173 if builtin.rust_slice { 174 out.next_section(); 175 writeln!(out, "template <typename T>"); 176 writeln!(out, "::std::size_t size_of();"); 177 writeln!(out, "template <typename T>"); 178 writeln!(out, "::std::size_t align_of();"); 179 } 180 181 ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING"); 182 ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR"); 183 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE"); 184 ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX"); 185 ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T"); 186 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY"); 187 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC"); 188 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN"); 189 ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR"); 190 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE"); 191 ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE"); 192 ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE"); 193 ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT"); 194 ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE"); 195 } 196 197 if builtin.rust_str_new_unchecked { 198 out.next_section(); 199 writeln!(out, "class Str::uninit {{}};"); 200 writeln!(out, "inline Str::Str(uninit) noexcept {{}}"); 201 } 202 203 if builtin.rust_slice_new { 204 out.next_section(); 205 writeln!(out, "template <typename T>"); 206 writeln!(out, "class Slice<T>::uninit {{}};"); 207 writeln!(out, "template <typename T>"); 208 writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}"); 209 } 210 211 out.begin_block(Block::Namespace("repr")); 212 213 if builtin.repr_fat { 214 include.array = true; 215 include.cstdint = true; 216 out.next_section(); 217 writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;"); 218 } 219 220 if builtin.ptr_len { 221 include.cstddef = true; 222 out.next_section(); 223 writeln!(out, "struct PtrLen final {{"); 224 writeln!(out, " void *ptr;"); 225 writeln!(out, " ::std::size_t len;"); 226 writeln!(out, "}};"); 227 } 228 229 out.end_block(Block::Namespace("repr")); 230 231 out.begin_block(Block::Namespace("detail")); 232 233 if builtin.maybe_uninit { 234 include.cstddef = true; 235 include.new = true; 236 out.next_section(); 237 writeln!(out, "template <typename T, typename = void *>"); 238 writeln!(out, "struct operator_new {{"); 239 writeln!( 240 out, 241 " void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}", 242 ); 243 writeln!(out, "}};"); 244 out.next_section(); 245 writeln!(out, "template <typename T>"); 246 writeln!( 247 out, 248 "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{", 249 ); 250 writeln!( 251 out, 252 " void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}", 253 ); 254 writeln!(out, "}};"); 255 } 256 257 if builtin.trycatch { 258 include.string = true; 259 out.next_section(); 260 writeln!(out, "class Fail final {{"); 261 writeln!(out, " ::rust::repr::PtrLen &throw$;"); 262 writeln!(out, "public:"); 263 writeln!( 264 out, 265 " Fail(::rust::repr::PtrLen &throw$) noexcept : throw$(throw$) {{}}", 266 ); 267 writeln!(out, " void operator()(char const *) noexcept;"); 268 writeln!(out, " void operator()(std::string const &) noexcept;"); 269 writeln!(out, "}};"); 270 } 271 272 out.end_block(Block::Namespace("detail")); 273 274 if builtin.manually_drop { 275 out.next_section(); 276 include.utility = true; 277 writeln!(out, "template <typename T>"); 278 writeln!(out, "union ManuallyDrop {{"); 279 writeln!(out, " T value;"); 280 writeln!( 281 out, 282 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}", 283 ); 284 writeln!(out, " ~ManuallyDrop() {{}}"); 285 writeln!(out, "}};"); 286 } 287 288 if builtin.maybe_uninit { 289 include.cstddef = true; 290 out.next_section(); 291 writeln!(out, "template <typename T>"); 292 writeln!(out, "union MaybeUninit {{"); 293 writeln!(out, " T value;"); 294 writeln!( 295 out, 296 " void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}", 297 ); 298 writeln!(out, " MaybeUninit() {{}}"); 299 writeln!(out, " ~MaybeUninit() {{}}"); 300 writeln!(out, "}};"); 301 } 302 303 out.begin_block(Block::AnonymousNamespace); 304 305 if builtin.rust_str_new_unchecked || builtin.rust_str_repr { 306 out.next_section(); 307 writeln!(out, "template <>"); 308 writeln!(out, "class impl<Str> final {{"); 309 writeln!(out, "public:"); 310 if builtin.rust_str_new_unchecked { 311 writeln!( 312 out, 313 " static Str new_unchecked(repr::Fat repr) noexcept {{", 314 ); 315 writeln!(out, " Str str = Str::uninit{{}};"); 316 writeln!(out, " str.repr = repr;"); 317 writeln!(out, " return str;"); 318 writeln!(out, " }}"); 319 } 320 if builtin.rust_str_repr { 321 writeln!(out, " static repr::Fat repr(Str str) noexcept {{"); 322 writeln!(out, " return str.repr;"); 323 writeln!(out, " }}"); 324 } 325 writeln!(out, "}};"); 326 } 327 328 if builtin.rust_slice_new || builtin.rust_slice_repr { 329 out.next_section(); 330 writeln!(out, "template <typename T>"); 331 writeln!(out, "class impl<Slice<T>> final {{"); 332 writeln!(out, "public:"); 333 if builtin.rust_slice_new { 334 writeln!(out, " static Slice<T> slice(repr::Fat repr) noexcept {{"); 335 writeln!(out, " Slice<T> slice = typename Slice<T>::uninit{{}};"); 336 writeln!(out, " slice.repr = repr;"); 337 writeln!(out, " return slice;"); 338 writeln!(out, " }}"); 339 } 340 if builtin.rust_slice_repr { 341 writeln!(out, " static repr::Fat repr(Slice<T> slice) noexcept {{"); 342 writeln!(out, " return slice.repr;"); 343 writeln!(out, " }}"); 344 } 345 writeln!(out, "}};"); 346 } 347 348 if builtin.rust_error { 349 out.next_section(); 350 writeln!(out, "template <>"); 351 writeln!(out, "class impl<Error> final {{"); 352 writeln!(out, "public:"); 353 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{"); 354 writeln!(out, " Error error;"); 355 writeln!(out, " error.msg = static_cast<char const *>(repr.ptr);"); 356 writeln!(out, " error.len = repr.len;"); 357 writeln!(out, " return error;"); 358 writeln!(out, " }}"); 359 writeln!(out, "}};"); 360 } 361 362 if builtin.destroy { 363 out.next_section(); 364 writeln!(out, "template <typename T>"); 365 writeln!(out, "void destroy(T *ptr) {{"); 366 writeln!(out, " ptr->~T();"); 367 writeln!(out, "}}"); 368 } 369 370 if builtin.deleter_if { 371 out.next_section(); 372 writeln!(out, "template <bool> struct deleter_if {{"); 373 writeln!(out, " template <typename T> void operator()(T *) {{}}"); 374 writeln!(out, "}};"); 375 out.next_section(); 376 writeln!(out, "template <> struct deleter_if<true> {{"); 377 writeln!( 378 out, 379 " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}", 380 ); 381 writeln!(out, "}};"); 382 } 383 384 if builtin.relocatable_or_array { 385 out.next_section(); 386 writeln!(out, "template <typename T>"); 387 writeln!(out, "struct IsRelocatableOrArray : IsRelocatable<T> {{}};"); 388 writeln!(out, "template <typename T, ::std::size_t N>"); 389 writeln!( 390 out, 391 "struct IsRelocatableOrArray<T[N]> : IsRelocatableOrArray<T> {{}};", 392 ); 393 } 394 395 out.end_block(Block::AnonymousNamespace); 396 out.end_block(Block::InlineNamespace("cxxbridge1")); 397 398 if builtin.trycatch { 399 out.begin_block(Block::Namespace("behavior")); 400 include.exception = true; 401 include.type_traits = true; 402 include.utility = true; 403 writeln!(out, "class missing {{}};"); 404 writeln!(out, "missing trycatch(...);"); 405 writeln!(out); 406 writeln!(out, "template <typename Try, typename Fail>"); 407 writeln!(out, "static typename ::std::enable_if<"); 408 writeln!( 409 out, 410 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),", 411 ); 412 writeln!(out, " missing>::value>::type"); 413 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{"); 414 writeln!(out, " func();"); 415 writeln!(out, "}} catch (::std::exception const &e) {{"); 416 writeln!(out, " fail(e.what());"); 417 writeln!(out, "}}"); 418 out.end_block(Block::Namespace("behavior")); 419 } 420 421 out.end_block(Block::Namespace("rust")); 422 } 423