blob: 8a65b5f8b7b338b4eb3bcf3c72b89d6f6d723090 [file] [log] [blame]
David Tolnay3374d8d2020-10-31 22:18:45 -07001use crate::gen::ifndef;
2use crate::gen::out::{Content, OutFile};
David Tolnay8c14d9a2020-10-31 21:52:38 -07003
David Tolnay3be0e1f2020-10-31 20:53:00 -07004#[derive(Default, PartialEq)]
5pub struct Builtins {
6 pub panic: bool,
7 pub rust_string: bool,
8 pub rust_str: bool,
9 pub rust_slice: bool,
10 pub rust_box: bool,
11 pub rust_vec: bool,
12 pub rust_fn: bool,
13 pub rust_isize: bool,
14 pub unsafe_bitcopy: bool,
15 pub rust_error: bool,
16 pub manually_drop: bool,
17 pub maybe_uninit: bool,
18 pub trycatch: bool,
David Tolnay919085c2020-10-31 22:32:22 -070019 pub ptr_len: bool,
David Tolnay3be0e1f2020-10-31 20:53:00 -070020 pub rust_str_new_unchecked: bool,
21 pub rust_str_repr: bool,
David Tolnay8c14d9a2020-10-31 21:52:38 -070022 pub content: Content,
David Tolnay3be0e1f2020-10-31 20:53:00 -070023}
24
25impl Builtins {
26 pub fn new() -> Self {
27 Builtins::default()
28 }
29}
David Tolnay3374d8d2020-10-31 22:18:45 -070030
31pub(super) fn write(out: &mut OutFile) {
32 if out.builtin == Default::default() {
33 return;
34 }
35
36 let include = &mut out.include;
37 let builtin = &mut out.builtin;
38 let out = &mut builtin.content;
39
40 out.begin_block("namespace rust");
41 out.begin_block("inline namespace cxxbridge05");
42 writeln!(out, "// #include \"rust/cxx.h\"");
43
44 ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
45
46 if builtin.rust_string {
47 out.next_section();
48 writeln!(out, "struct unsafe_bitcopy_t;");
49 }
50
51 if builtin.rust_error {
52 out.begin_block("namespace");
53 writeln!(out, "template <typename T>");
54 writeln!(out, "class impl;");
55 out.end_block("namespace");
56 }
57
58 ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
59 ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
60 ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
61 ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
62 ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
63 ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
64 ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
65 ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
66 ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
67
68 if builtin.manually_drop {
69 out.next_section();
70 include.utility = true;
71 writeln!(out, "template <typename T>");
72 writeln!(out, "union ManuallyDrop {{");
73 writeln!(out, " T value;");
74 writeln!(
75 out,
76 " ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
77 );
78 writeln!(out, " ~ManuallyDrop() {{}}");
79 writeln!(out, "}};");
80 }
81
82 if builtin.maybe_uninit {
83 out.next_section();
84 writeln!(out, "template <typename T>");
85 writeln!(out, "union MaybeUninit {{");
86 writeln!(out, " T value;");
87 writeln!(out, " MaybeUninit() {{}}");
88 writeln!(out, " ~MaybeUninit() {{}}");
89 writeln!(out, "}};");
90 }
91
92 out.begin_block("namespace");
93
David Tolnay919085c2020-10-31 22:32:22 -070094 if builtin.ptr_len {
David Tolnay3374d8d2020-10-31 22:18:45 -070095 out.begin_block("namespace repr");
96 writeln!(out, "struct PtrLen final {{");
97 writeln!(out, " const void *ptr;");
98 writeln!(out, " size_t len;");
99 writeln!(out, "}};");
100 out.end_block("namespace repr");
101 }
102
103 if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
104 out.next_section();
105 writeln!(out, "template <>");
106 writeln!(out, "class impl<Str> final {{");
107 writeln!(out, "public:");
108 if builtin.rust_str_new_unchecked {
109 writeln!(
110 out,
111 " static Str new_unchecked(repr::PtrLen repr) noexcept {{",
112 );
113 writeln!(out, " Str str;");
114 writeln!(out, " str.ptr = static_cast<const char *>(repr.ptr);");
115 writeln!(out, " str.len = repr.len;");
116 writeln!(out, " return str;");
117 writeln!(out, " }}");
118 }
119 if builtin.rust_str_repr {
120 writeln!(out, " static repr::PtrLen repr(Str str) noexcept {{");
121 writeln!(out, " return repr::PtrLen{{str.ptr, str.len}};");
122 writeln!(out, " }}");
123 }
124 writeln!(out, "}};");
125 }
126
127 if builtin.rust_error {
128 out.next_section();
129 writeln!(out, "template <>");
130 writeln!(out, "class impl<Error> final {{");
131 writeln!(out, "public:");
132 writeln!(out, " static Error error(repr::PtrLen repr) noexcept {{");
133 writeln!(out, " Error error;");
134 writeln!(out, " error.msg = static_cast<const char *>(repr.ptr);");
135 writeln!(out, " error.len = repr.len;");
136 writeln!(out, " return error;");
137 writeln!(out, " }}");
138 writeln!(out, "}};");
139 }
140
141 out.end_block("namespace");
142 out.end_block("namespace cxxbridge05");
143
144 if builtin.trycatch {
145 out.begin_block("namespace behavior");
146 include.exception = true;
147 include.type_traits = true;
148 include.utility = true;
149 writeln!(out, "class missing {{}};");
150 writeln!(out, "missing trycatch(...);");
151 writeln!(out);
152 writeln!(out, "template <typename Try, typename Fail>");
153 writeln!(out, "static typename ::std::enable_if<");
154 writeln!(
155 out,
156 " ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
157 );
158 writeln!(out, " missing>::value>::type");
159 writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
160 writeln!(out, " func();");
161 writeln!(out, "}} catch (const ::std::exception &e) {{");
162 writeln!(out, " fail(e.what());");
163 writeln!(out, "}}");
164 out.end_block("namespace behavior");
165 }
166
167 out.end_block("namespace rust");
168}