blob: 0a664d02e4a78b9748da9f0ba4627f8ba41bc9a7 [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
Myron Ahneba35cf2020-02-05 19:41:51 +070087#ifndef CXXBRIDGE02_RUST_VEC
88#define CXXBRIDGE02_RUST_VEC
89template <typename T>
90class Vec final {
91public:
92 size_t size() const noexcept;
93 explicit operator std::vector<T>() const noexcept;
94
95private:
96 Vec() noexcept;
97 Vec(const Vec &other) noexcept;
98 Vec &operator=(Vec other) noexcept;
99 void drop() noexcept;
David Tolnay37dd7e12020-04-25 12:51:59 -0700100
Myron Ahneba35cf2020-02-05 19:41:51 +0700101 // Repr
102 const T *ptr;
103 size_t len;
104 size_t capacity;
105};
106#endif // CXXBRIDGE02_RUST_VEC
107
David Tolnayefe81052020-04-14 16:28:24 -0700108#ifndef CXXBRIDGE02_RUST_SLICE
109#define CXXBRIDGE02_RUST_SLICE
110template <typename T>
111class Slice final {
112public:
113 Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
114 Slice(const Slice<T> &) noexcept = default;
115
116 Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
117
118 Slice &operator=(Slice<T> other) noexcept {
119 this->repr = other.repr;
120 return *this;
121 }
122
123 const T *data() const noexcept { return this->repr.ptr; }
124 size_t size() const noexcept { return this->repr.len; }
125 size_t length() const noexcept { return this->repr.len; }
126
127 // Repr is PRIVATE; must not be used other than by our generated code.
128 //
129 // At present this class is only used for &[u8] slices.
130 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700131 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700132 struct Repr {
133 const T *ptr;
134 size_t len;
135 };
136 Slice(Repr repr_) noexcept : repr(repr_) {}
137 explicit operator Repr() noexcept { return this->repr; }
138
139private:
140 Repr repr;
141};
142#endif // CXXBRIDGE02_RUST_SLICE
143
David Tolnay8c730492020-03-13 01:29:06 -0700144#ifndef CXXBRIDGE02_RUST_BOX
145#define CXXBRIDGE02_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700146template <typename T>
147class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400148public:
David Tolnayf6292372020-03-01 21:09:11 -0800149 using value_type = T;
David Tolnay9f921372020-03-01 21:09:25 -0800150 using const_pointer = typename std::add_pointer<
151 typename std::add_const<value_type>::type>::type;
152 using pointer = typename std::add_pointer<value_type>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800153
David Tolnay324437a2020-03-01 13:02:24 -0800154 Box(const Box &other) : Box(*other) {}
David Tolnay33169bd2020-03-06 13:02:08 -0800155 Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
David Tolnay7db7dad2020-04-11 14:12:49 -0700156 explicit Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -0400157 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800158 ::new (this->ptr) T(val);
David Tolnay7db73692019-10-20 14:51:12 -0400159 }
David Tolnay7db7dad2020-04-11 14:12:49 -0700160 explicit Box(T &&val) {
David Tolnay47b3cf22020-04-11 00:54:39 -0700161 this->uninit();
162 ::new (this->ptr) T(std::move(val));
163 }
David Tolnay324437a2020-03-01 13:02:24 -0800164 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -0400165 if (this != &other) {
David Tolnay33169bd2020-03-06 13:02:08 -0800166 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400167 **this = *other;
168 } else {
169 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800170 ::new (this->ptr) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -0400171 }
172 }
173 return *this;
174 }
David Tolnay324437a2020-03-01 13:02:24 -0800175 Box &operator=(Box &&other) noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800176 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400177 this->drop();
178 }
David Tolnay33169bd2020-03-06 13:02:08 -0800179 this->ptr = other.ptr;
180 other.ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400181 return *this;
182 }
David Tolnay324437a2020-03-01 13:02:24 -0800183 ~Box() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800184 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400185 this->drop();
186 }
187 }
188
David Tolnay33169bd2020-03-06 13:02:08 -0800189 const T *operator->() const noexcept { return this->ptr; }
190 const T &operator*() const noexcept { return *this->ptr; }
191 T *operator->() noexcept { return this->ptr; }
192 T &operator*() noexcept { return *this->ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400193
David Tolnayf262d382020-04-11 22:12:40 -0700194 template <typename... Fields>
195 static Box in_place(Fields &&... fields) {
David Tolnay7ce59fc2020-04-11 11:46:33 -0700196 Box box;
197 box.uninit();
198 ::new (box.ptr) T{std::forward<Fields>(fields)...};
199 return box;
200 }
201
David Tolnay7db73692019-10-20 14:51:12 -0400202 // Important: requires that `raw` came from an into_raw call. Do not pass a
203 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800204 static Box from_raw(T *raw) noexcept {
205 Box box;
David Tolnay33169bd2020-03-06 13:02:08 -0800206 box.ptr = raw;
David Tolnay7db73692019-10-20 14:51:12 -0400207 return box;
208 }
209
210 T *into_raw() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800211 T *raw = this->ptr;
212 this->ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400213 return raw;
214 }
215
216private:
David Tolnay324437a2020-03-01 13:02:24 -0800217 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400218 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400219 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800220 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400221};
David Tolnay8c730492020-03-13 01:29:06 -0700222#endif // CXXBRIDGE02_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400223
David Tolnay75dca2e2020-03-25 20:17:52 -0700224#ifndef CXXBRIDGE02_RUST_FN
225#define CXXBRIDGE02_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700226template <typename Signature, bool Throws = false>
227class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700228
229template <typename Ret, typename... Args, bool Throws>
230class Fn<Ret(Args...), Throws> {
231public:
David Tolnay533d4582020-04-08 20:29:14 -0700232 Ret operator()(Args... args) const noexcept(!Throws);
233 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700234
235private:
236 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
237 void *fn;
238};
239
David Tolnayf262d382020-04-11 22:12:40 -0700240template <typename Signature>
241using TryFn = Fn<Signature, true>;
David Tolnay75dca2e2020-03-25 20:17:52 -0700242#endif // CXXBRIDGE02_RUST_FN
243
David Tolnayb7a7cb62020-03-17 21:18:40 -0700244#ifndef CXXBRIDGE02_RUST_ERROR
245#define CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700246class Error final : std::exception {
247public:
248 Error(const Error &);
249 Error(Error &&) noexcept;
250 Error(Str::Repr) noexcept;
251 ~Error() noexcept;
252 const char *what() const noexcept override;
253
254private:
255 Str::Repr msg;
256};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700257#endif // CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700258
David Tolnayb8a6fb22020-04-10 11:17:28 -0700259#if defined(_WIN32)
260using isize = SSIZE_T;
261#else
262using isize = ssize_t;
263#endif
David Tolnayb8a6fb22020-04-10 11:17:28 -0700264
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