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