blob: a96e6faa30db1415b0332d143a2b788114ebe685 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001#pragma once
2#include <array>
David Tolnay30430f12020-03-19 20:49:00 -07003#include <cstddef>
David Tolnay7db73692019-10-20 14:51:12 -04004#include <cstdint>
David Tolnayb7a7cb62020-03-17 21:18:40 -07005#include <exception>
David Tolnay001102a2020-03-01 20:05:04 -08006#include <iosfwd>
David Tolnay7db73692019-10-20 14:51:12 -04007#include <string>
David Tolnayf6292372020-03-01 21:09:11 -08008#include <type_traits>
David Tolnay4791f1c2020-03-17 21:53:16 -07009#include <utility>
David Tolnay37dd7e12020-04-25 12:51:59 -070010#include <vector>
David Tolnay59b5ba12020-04-10 11:32:19 -070011#if defined(_WIN32)
12#include <BaseTsd.h>
13#endif
David Tolnay7db73692019-10-20 14:51:12 -040014
David Tolnay750755e2020-03-01 13:04:08 -080015namespace rust {
David Tolnay8c730492020-03-13 01:29:06 -070016inline namespace cxxbridge02 {
David Tolnay7db73692019-10-20 14:51:12 -040017
David Tolnayd1e2efc2020-03-03 22:25:43 -080018struct unsafe_bitcopy_t;
19
David Tolnayb7a7cb62020-03-17 21:18:40 -070020#ifndef CXXBRIDGE02_RUST_STRING
21#define CXXBRIDGE02_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080022class String final {
David Tolnay7db73692019-10-20 14:51:12 -040023public:
David Tolnay56082162020-03-01 12:57:33 -080024 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080025 String(const String &) noexcept;
26 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080027 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080028
29 String(const std::string &);
30 String(const char *);
31
32 String &operator=(const String &) noexcept;
33 String &operator=(String &&) noexcept;
34
David Tolnay404d6892020-03-01 20:19:41 -080035 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040036
37 // Note: no null terminator.
38 const char *data() const noexcept;
39 size_t size() const noexcept;
40 size_t length() const noexcept;
41
David Tolnayd1e2efc2020-03-03 22:25:43 -080042 // Internal API only intended for the cxxbridge code generator.
43 String(unsafe_bitcopy_t, const String &) noexcept;
44
David Tolnay7db73692019-10-20 14:51:12 -040045private:
46 // Size and alignment statically verified by rust_string.rs.
47 std::array<uintptr_t, 3> repr;
48};
David Tolnayb7a7cb62020-03-17 21:18:40 -070049#endif // CXXBRIDGE02_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040050
David Tolnayb7a7cb62020-03-17 21:18:40 -070051#ifndef CXXBRIDGE02_RUST_STR
52#define CXXBRIDGE02_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080053class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040054public:
David Tolnay09dbe752020-03-01 13:00:40 -080055 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080056 Str(const Str &) noexcept;
57
David Tolnay851677c2020-03-01 23:49:46 -080058 Str(const std::string &);
59 Str(const char *);
60 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080061
62 Str &operator=(Str) noexcept;
63
David Tolnay404d6892020-03-01 20:19:41 -080064 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040065
66 // Note: no null terminator.
67 const char *data() const noexcept;
68 size_t size() const noexcept;
69 size_t length() const noexcept;
70
71 // Repr is PRIVATE; must not be used other than by our generated code.
72 //
73 // Not necessarily ABI compatible with &str. Codegen will translate to
74 // cxx::rust_str::RustStr which matches this layout.
75 struct Repr {
76 const char *ptr;
77 size_t len;
78 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080079 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080080 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040081
82private:
83 Repr repr;
84};
David Tolnayb7a7cb62020-03-17 21:18:40 -070085#endif // CXXBRIDGE02_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040086
David Tolnayefe81052020-04-14 16:28:24 -070087#ifndef CXXBRIDGE02_RUST_SLICE
88#define CXXBRIDGE02_RUST_SLICE
89template <typename T>
90class Slice final {
91public:
92 Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
93 Slice(const Slice<T> &) noexcept = default;
94
95 Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
96
97 Slice &operator=(Slice<T> other) noexcept {
98 this->repr = other.repr;
99 return *this;
100 }
101
102 const T *data() const noexcept { return this->repr.ptr; }
103 size_t size() const noexcept { return this->repr.len; }
104 size_t length() const noexcept { return this->repr.len; }
105
106 // Repr is PRIVATE; must not be used other than by our generated code.
107 //
108 // At present this class is only used for &[u8] slices.
109 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700110 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700111 struct Repr {
112 const T *ptr;
113 size_t len;
114 };
115 Slice(Repr repr_) noexcept : repr(repr_) {}
116 explicit operator Repr() noexcept { return this->repr; }
117
118private:
119 Repr repr;
120};
121#endif // CXXBRIDGE02_RUST_SLICE
122
David Tolnay8c730492020-03-13 01:29:06 -0700123#ifndef CXXBRIDGE02_RUST_BOX
124#define CXXBRIDGE02_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700125template <typename T>
126class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400127public:
David Tolnayf6292372020-03-01 21:09:11 -0800128 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700129 using const_pointer =
130 typename std::add_pointer<typename std::add_const<T>::type>::type;
131 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800132
David Tolnay324437a2020-03-01 13:02:24 -0800133 Box(const Box &other) : Box(*other) {}
David Tolnay33169bd2020-03-06 13:02:08 -0800134 Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
David Tolnay7db7dad2020-04-11 14:12:49 -0700135 explicit Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -0400136 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800137 ::new (this->ptr) T(val);
David Tolnay7db73692019-10-20 14:51:12 -0400138 }
David Tolnay7db7dad2020-04-11 14:12:49 -0700139 explicit Box(T &&val) {
David Tolnay47b3cf22020-04-11 00:54:39 -0700140 this->uninit();
141 ::new (this->ptr) T(std::move(val));
142 }
David Tolnay324437a2020-03-01 13:02:24 -0800143 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -0400144 if (this != &other) {
David Tolnay33169bd2020-03-06 13:02:08 -0800145 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400146 **this = *other;
147 } else {
148 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800149 ::new (this->ptr) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -0400150 }
151 }
152 return *this;
153 }
David Tolnay324437a2020-03-01 13:02:24 -0800154 Box &operator=(Box &&other) noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800155 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400156 this->drop();
157 }
David Tolnay33169bd2020-03-06 13:02:08 -0800158 this->ptr = other.ptr;
159 other.ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400160 return *this;
161 }
David Tolnay324437a2020-03-01 13:02:24 -0800162 ~Box() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800163 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400164 this->drop();
165 }
166 }
167
David Tolnay33169bd2020-03-06 13:02:08 -0800168 const T *operator->() const noexcept { return this->ptr; }
169 const T &operator*() const noexcept { return *this->ptr; }
170 T *operator->() noexcept { return this->ptr; }
171 T &operator*() noexcept { return *this->ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400172
David Tolnayf262d382020-04-11 22:12:40 -0700173 template <typename... Fields>
174 static Box in_place(Fields &&... fields) {
David Tolnay7ce59fc2020-04-11 11:46:33 -0700175 Box box;
176 box.uninit();
177 ::new (box.ptr) T{std::forward<Fields>(fields)...};
178 return box;
179 }
180
David Tolnay7db73692019-10-20 14:51:12 -0400181 // Important: requires that `raw` came from an into_raw call. Do not pass a
182 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800183 static Box from_raw(T *raw) noexcept {
184 Box box;
David Tolnay33169bd2020-03-06 13:02:08 -0800185 box.ptr = raw;
David Tolnay7db73692019-10-20 14:51:12 -0400186 return box;
187 }
188
189 T *into_raw() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800190 T *raw = this->ptr;
191 this->ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400192 return raw;
193 }
194
195private:
David Tolnay324437a2020-03-01 13:02:24 -0800196 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400197 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400198 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800199 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400200};
David Tolnay8c730492020-03-13 01:29:06 -0700201#endif // CXXBRIDGE02_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400202
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700203#ifndef CXXBRIDGE02_RUST_VEC
204#define CXXBRIDGE02_RUST_VEC
205template <typename T>
206class Vec final {
207public:
208 size_t size() const noexcept;
209
210private:
211 Vec() noexcept;
212 Vec(const Vec &other) noexcept;
213 Vec &operator=(Vec other) noexcept;
214 void drop() noexcept;
215
216 // Size and alignment statically verified by rust_vec.rs.
217 std::array<uintptr_t, 3> repr;
218};
219#endif // CXXBRIDGE02_RUST_VEC
220
David Tolnay75dca2e2020-03-25 20:17:52 -0700221#ifndef CXXBRIDGE02_RUST_FN
222#define CXXBRIDGE02_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700223template <typename Signature, bool Throws = false>
224class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700225
226template <typename Ret, typename... Args, bool Throws>
227class Fn<Ret(Args...), Throws> {
228public:
David Tolnay533d4582020-04-08 20:29:14 -0700229 Ret operator()(Args... args) const noexcept(!Throws);
230 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700231
232private:
233 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
234 void *fn;
235};
236
David Tolnayf262d382020-04-11 22:12:40 -0700237template <typename Signature>
238using TryFn = Fn<Signature, true>;
David Tolnay75dca2e2020-03-25 20:17:52 -0700239#endif // CXXBRIDGE02_RUST_FN
240
David Tolnayb7a7cb62020-03-17 21:18:40 -0700241#ifndef CXXBRIDGE02_RUST_ERROR
242#define CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700243class Error final : std::exception {
244public:
245 Error(const Error &);
246 Error(Error &&) noexcept;
247 Error(Str::Repr) noexcept;
248 ~Error() noexcept;
249 const char *what() const noexcept override;
250
251private:
252 Str::Repr msg;
253};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700254#endif // CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700255
David Tolnayb8a6fb22020-04-10 11:17:28 -0700256#ifndef CXXBRIDGE02_RUST_ISIZE
257#define CXXBRIDGE02_RUST_ISIZE
258#if defined(_WIN32)
259using isize = SSIZE_T;
260#else
261using isize = ssize_t;
262#endif
263#endif // CXXBRIDGE02_RUST_ISIZE
264
David Tolnay851677c2020-03-01 23:49:46 -0800265std::ostream &operator<<(std::ostream &, const String &);
266std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400267
David Tolnay3b0c9882020-03-01 14:08:57 -0800268// Snake case aliases for use in code that uses this style for type names.
269using string = String;
270using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700271template <class T>
272using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700273using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700274template <typename Signature, bool Throws = false>
275using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700276template <typename Signature>
277using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800278
David Tolnayb7a7cb62020-03-17 21:18:40 -0700279#ifndef CXXBRIDGE02_RUST_BITCOPY
280#define CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800281struct unsafe_bitcopy_t {
282 explicit unsafe_bitcopy_t() = default;
283};
284constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700285#endif // CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800286
David Tolnay75dca2e2020-03-25 20:17:52 -0700287template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700288Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700289 return (*this->trampoline)(std::move(args)..., this->fn);
290}
291
David Tolnaya23129c2020-04-08 20:08:21 -0700292template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700293Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700294 return *this;
295}
296
David Tolnay8c730492020-03-13 01:29:06 -0700297} // namespace cxxbridge02
David Tolnay750755e2020-03-01 13:04:08 -0800298} // namespace rust