blob: 637372aba701166019238f098578ee473cf438e8 [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 Tolnay59b5ba12020-04-10 11:32:19 -070010#if defined(_WIN32)
11#include <BaseTsd.h>
12#endif
David Tolnay7db73692019-10-20 14:51:12 -040013
David Tolnay750755e2020-03-01 13:04:08 -080014namespace rust {
David Tolnay8c730492020-03-13 01:29:06 -070015inline namespace cxxbridge02 {
David Tolnay7db73692019-10-20 14:51:12 -040016
David Tolnayd1e2efc2020-03-03 22:25:43 -080017struct unsafe_bitcopy_t;
18
David Tolnayb7a7cb62020-03-17 21:18:40 -070019#ifndef CXXBRIDGE02_RUST_STRING
20#define CXXBRIDGE02_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080021class String final {
David Tolnay7db73692019-10-20 14:51:12 -040022public:
David Tolnay56082162020-03-01 12:57:33 -080023 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080024 String(const String &) noexcept;
25 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080026 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080027
28 String(const std::string &);
29 String(const char *);
30
31 String &operator=(const String &) noexcept;
32 String &operator=(String &&) noexcept;
33
David Tolnay404d6892020-03-01 20:19:41 -080034 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040035
36 // Note: no null terminator.
37 const char *data() const noexcept;
38 size_t size() const noexcept;
39 size_t length() const noexcept;
40
David Tolnayd1e2efc2020-03-03 22:25:43 -080041 // Internal API only intended for the cxxbridge code generator.
42 String(unsafe_bitcopy_t, const String &) noexcept;
43
David Tolnay7db73692019-10-20 14:51:12 -040044private:
45 // Size and alignment statically verified by rust_string.rs.
46 std::array<uintptr_t, 3> repr;
47};
David Tolnayb7a7cb62020-03-17 21:18:40 -070048#endif // CXXBRIDGE02_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040049
David Tolnayb7a7cb62020-03-17 21:18:40 -070050#ifndef CXXBRIDGE02_RUST_STR
51#define CXXBRIDGE02_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080052class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040053public:
David Tolnay09dbe752020-03-01 13:00:40 -080054 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080055 Str(const Str &) noexcept;
56
David Tolnay851677c2020-03-01 23:49:46 -080057 Str(const std::string &);
58 Str(const char *);
59 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080060
61 Str &operator=(Str) noexcept;
62
David Tolnay404d6892020-03-01 20:19:41 -080063 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040064
65 // Note: no null terminator.
66 const char *data() const noexcept;
67 size_t size() const noexcept;
68 size_t length() const noexcept;
69
70 // Repr is PRIVATE; must not be used other than by our generated code.
71 //
72 // Not necessarily ABI compatible with &str. Codegen will translate to
73 // cxx::rust_str::RustStr which matches this layout.
74 struct Repr {
75 const char *ptr;
76 size_t len;
77 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080078 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080079 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040080
81private:
82 Repr repr;
83};
David Tolnayb7a7cb62020-03-17 21:18:40 -070084#endif // CXXBRIDGE02_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040085
David Tolnayefe81052020-04-14 16:28:24 -070086#ifndef CXXBRIDGE02_RUST_SLICE
87#define CXXBRIDGE02_RUST_SLICE
88template <typename T>
89class Slice final {
90public:
91 Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
92 Slice(const Slice<T> &) noexcept = default;
93
94 Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
95
96 Slice &operator=(Slice<T> other) noexcept {
97 this->repr = other.repr;
98 return *this;
99 }
100
101 const T *data() const noexcept { return this->repr.ptr; }
102 size_t size() const noexcept { return this->repr.len; }
103 size_t length() const noexcept { return this->repr.len; }
104
105 // Repr is PRIVATE; must not be used other than by our generated code.
106 //
107 // At present this class is only used for &[u8] slices.
108 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700109 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700110 struct Repr {
111 const T *ptr;
112 size_t len;
113 };
114 Slice(Repr repr_) noexcept : repr(repr_) {}
115 explicit operator Repr() noexcept { return this->repr; }
116
117private:
118 Repr repr;
119};
120#endif // CXXBRIDGE02_RUST_SLICE
121
David Tolnay8c730492020-03-13 01:29:06 -0700122#ifndef CXXBRIDGE02_RUST_BOX
123#define CXXBRIDGE02_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700124template <typename T>
125class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400126public:
David Tolnayf6292372020-03-01 21:09:11 -0800127 using value_type = T;
David Tolnay9f921372020-03-01 21:09:25 -0800128 using const_pointer = typename std::add_pointer<
129 typename std::add_const<value_type>::type>::type;
130 using pointer = typename std::add_pointer<value_type>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800131
David Tolnay324437a2020-03-01 13:02:24 -0800132 Box(const Box &other) : Box(*other) {}
David Tolnay33169bd2020-03-06 13:02:08 -0800133 Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
David Tolnay7db7dad2020-04-11 14:12:49 -0700134 explicit Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -0400135 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800136 ::new (this->ptr) T(val);
David Tolnay7db73692019-10-20 14:51:12 -0400137 }
David Tolnay7db7dad2020-04-11 14:12:49 -0700138 explicit Box(T &&val) {
David Tolnay47b3cf22020-04-11 00:54:39 -0700139 this->uninit();
140 ::new (this->ptr) T(std::move(val));
141 }
David Tolnay324437a2020-03-01 13:02:24 -0800142 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -0400143 if (this != &other) {
David Tolnay33169bd2020-03-06 13:02:08 -0800144 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400145 **this = *other;
146 } else {
147 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800148 ::new (this->ptr) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -0400149 }
150 }
151 return *this;
152 }
David Tolnay324437a2020-03-01 13:02:24 -0800153 Box &operator=(Box &&other) noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800154 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400155 this->drop();
156 }
David Tolnay33169bd2020-03-06 13:02:08 -0800157 this->ptr = other.ptr;
158 other.ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400159 return *this;
160 }
David Tolnay324437a2020-03-01 13:02:24 -0800161 ~Box() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800162 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400163 this->drop();
164 }
165 }
166
David Tolnay33169bd2020-03-06 13:02:08 -0800167 const T *operator->() const noexcept { return this->ptr; }
168 const T &operator*() const noexcept { return *this->ptr; }
169 T *operator->() noexcept { return this->ptr; }
170 T &operator*() noexcept { return *this->ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400171
David Tolnayf262d382020-04-11 22:12:40 -0700172 template <typename... Fields>
173 static Box in_place(Fields &&... fields) {
David Tolnay7ce59fc2020-04-11 11:46:33 -0700174 Box box;
175 box.uninit();
176 ::new (box.ptr) T{std::forward<Fields>(fields)...};
177 return box;
178 }
179
David Tolnay7db73692019-10-20 14:51:12 -0400180 // Important: requires that `raw` came from an into_raw call. Do not pass a
181 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800182 static Box from_raw(T *raw) noexcept {
183 Box box;
David Tolnay33169bd2020-03-06 13:02:08 -0800184 box.ptr = raw;
David Tolnay7db73692019-10-20 14:51:12 -0400185 return box;
186 }
187
188 T *into_raw() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800189 T *raw = this->ptr;
190 this->ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400191 return raw;
192 }
193
194private:
David Tolnay324437a2020-03-01 13:02:24 -0800195 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400196 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400197 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800198 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400199};
David Tolnay8c730492020-03-13 01:29:06 -0700200#endif // CXXBRIDGE02_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400201
David Tolnay75dca2e2020-03-25 20:17:52 -0700202#ifndef CXXBRIDGE02_RUST_FN
203#define CXXBRIDGE02_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700204template <typename Signature, bool Throws = false>
205class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700206
207template <typename Ret, typename... Args, bool Throws>
208class Fn<Ret(Args...), Throws> {
209public:
David Tolnay533d4582020-04-08 20:29:14 -0700210 Ret operator()(Args... args) const noexcept(!Throws);
211 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700212
213private:
214 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
215 void *fn;
216};
217
David Tolnayf262d382020-04-11 22:12:40 -0700218template <typename Signature>
219using TryFn = Fn<Signature, true>;
David Tolnay75dca2e2020-03-25 20:17:52 -0700220#endif // CXXBRIDGE02_RUST_FN
221
David Tolnayb7a7cb62020-03-17 21:18:40 -0700222#ifndef CXXBRIDGE02_RUST_ERROR
223#define CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700224class Error final : std::exception {
225public:
226 Error(const Error &);
227 Error(Error &&) noexcept;
228 Error(Str::Repr) noexcept;
229 ~Error() noexcept;
230 const char *what() const noexcept override;
231
232private:
233 Str::Repr msg;
234};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700235#endif // CXXBRIDGE02_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700236
David Tolnayb8a6fb22020-04-10 11:17:28 -0700237#ifndef CXXBRIDGE02_RUST_ISIZE
238#define CXXBRIDGE02_RUST_ISIZE
239#if defined(_WIN32)
240using isize = SSIZE_T;
241#else
242using isize = ssize_t;
243#endif
244#endif // CXXBRIDGE02_RUST_ISIZE
245
David Tolnay851677c2020-03-01 23:49:46 -0800246std::ostream &operator<<(std::ostream &, const String &);
247std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400248
David Tolnay3b0c9882020-03-01 14:08:57 -0800249// Snake case aliases for use in code that uses this style for type names.
250using string = String;
251using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700252template <class T>
253using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700254using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700255template <typename Signature, bool Throws = false>
256using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700257template <typename Signature>
258using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800259
David Tolnayb7a7cb62020-03-17 21:18:40 -0700260#ifndef CXXBRIDGE02_RUST_BITCOPY
261#define CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800262struct unsafe_bitcopy_t {
263 explicit unsafe_bitcopy_t() = default;
264};
265constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnayb7a7cb62020-03-17 21:18:40 -0700266#endif // CXXBRIDGE02_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -0800267
David Tolnay75dca2e2020-03-25 20:17:52 -0700268template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700269Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700270 return (*this->trampoline)(std::move(args)..., this->fn);
271}
272
David Tolnaya23129c2020-04-08 20:08:21 -0700273template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700274Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700275 return *this;
276}
277
David Tolnay8c730492020-03-13 01:29:06 -0700278} // namespace cxxbridge02
David Tolnay750755e2020-03-01 13:04:08 -0800279} // namespace rust