blob: b56c14a9eb16234c650e5a1faa9d10126701991b [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 Tolnay69601622020-04-29 18:48:36 -070016inline namespace cxxbridge03 {
David Tolnay7db73692019-10-20 14:51:12 -040017
David Tolnay69601622020-04-29 18:48:36 -070018#ifndef CXXBRIDGE03_RUST_BITCOPY
19#define CXXBRIDGE03_RUST_BITCOPY
David Tolnay313b10e2020-04-25 16:30:51 -070020struct unsafe_bitcopy_t {
21 explicit unsafe_bitcopy_t() = default;
22};
23constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnay69601622020-04-29 18:48:36 -070024#endif // CXXBRIDGE03_RUST_BITCOPY
David Tolnayd1e2efc2020-03-03 22:25:43 -080025
David Tolnay69601622020-04-29 18:48:36 -070026#ifndef CXXBRIDGE03_RUST_STRING
27#define CXXBRIDGE03_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080028class String final {
David Tolnay7db73692019-10-20 14:51:12 -040029public:
David Tolnay56082162020-03-01 12:57:33 -080030 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080031 String(const String &) noexcept;
32 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080033 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080034
35 String(const std::string &);
36 String(const char *);
37
38 String &operator=(const String &) noexcept;
39 String &operator=(String &&) noexcept;
40
David Tolnay404d6892020-03-01 20:19:41 -080041 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040042
43 // Note: no null terminator.
44 const char *data() const noexcept;
45 size_t size() const noexcept;
46 size_t length() const noexcept;
47
David Tolnayd1e2efc2020-03-03 22:25:43 -080048 // Internal API only intended for the cxxbridge code generator.
49 String(unsafe_bitcopy_t, const String &) noexcept;
50
David Tolnay7db73692019-10-20 14:51:12 -040051private:
52 // Size and alignment statically verified by rust_string.rs.
53 std::array<uintptr_t, 3> repr;
54};
David Tolnay69601622020-04-29 18:48:36 -070055#endif // CXXBRIDGE03_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040056
David Tolnay69601622020-04-29 18:48:36 -070057#ifndef CXXBRIDGE03_RUST_STR
58#define CXXBRIDGE03_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080059class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040060public:
David Tolnay09dbe752020-03-01 13:00:40 -080061 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080062 Str(const Str &) noexcept;
63
David Tolnay851677c2020-03-01 23:49:46 -080064 Str(const std::string &);
65 Str(const char *);
66 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080067
68 Str &operator=(Str) noexcept;
69
David Tolnay404d6892020-03-01 20:19:41 -080070 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040071
72 // Note: no null terminator.
73 const char *data() const noexcept;
74 size_t size() const noexcept;
75 size_t length() const noexcept;
76
77 // Repr is PRIVATE; must not be used other than by our generated code.
78 //
79 // Not necessarily ABI compatible with &str. Codegen will translate to
80 // cxx::rust_str::RustStr which matches this layout.
81 struct Repr {
82 const char *ptr;
83 size_t len;
84 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080085 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080086 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040087
88private:
89 Repr repr;
90};
David Tolnay69601622020-04-29 18:48:36 -070091#endif // CXXBRIDGE03_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040092
David Tolnay69601622020-04-29 18:48:36 -070093#ifndef CXXBRIDGE03_RUST_SLICE
94#define CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070095template <typename T>
96class Slice final {
97public:
98 Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
99 Slice(const Slice<T> &) noexcept = default;
100
David Tolnay8c54eec2020-05-12 20:08:20 -0700101 Slice(const T *s, size_t size) noexcept : repr(Repr{s, size}) {}
David Tolnayefe81052020-04-14 16:28:24 -0700102
103 Slice &operator=(Slice<T> other) noexcept {
104 this->repr = other.repr;
105 return *this;
106 }
107
108 const T *data() const noexcept { return this->repr.ptr; }
109 size_t size() const noexcept { return this->repr.len; }
110 size_t length() const noexcept { return this->repr.len; }
111
112 // Repr is PRIVATE; must not be used other than by our generated code.
113 //
114 // At present this class is only used for &[u8] slices.
115 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700116 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700117 struct Repr {
118 const T *ptr;
119 size_t len;
120 };
121 Slice(Repr repr_) noexcept : repr(repr_) {}
122 explicit operator Repr() noexcept { return this->repr; }
123
124private:
125 Repr repr;
126};
David Tolnay69601622020-04-29 18:48:36 -0700127#endif // CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700128
David Tolnay69601622020-04-29 18:48:36 -0700129#ifndef CXXBRIDGE03_RUST_BOX
130#define CXXBRIDGE03_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700131template <typename T>
132class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400133public:
David Tolnayf6292372020-03-01 21:09:11 -0800134 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700135 using const_pointer =
136 typename std::add_pointer<typename std::add_const<T>::type>::type;
137 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800138
David Tolnay324437a2020-03-01 13:02:24 -0800139 Box(const Box &other) : Box(*other) {}
David Tolnay33169bd2020-03-06 13:02:08 -0800140 Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
David Tolnay7db7dad2020-04-11 14:12:49 -0700141 explicit Box(const T &val) {
David Tolnay7db73692019-10-20 14:51:12 -0400142 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800143 ::new (this->ptr) T(val);
David Tolnay7db73692019-10-20 14:51:12 -0400144 }
David Tolnay7db7dad2020-04-11 14:12:49 -0700145 explicit Box(T &&val) {
David Tolnay47b3cf22020-04-11 00:54:39 -0700146 this->uninit();
147 ::new (this->ptr) T(std::move(val));
148 }
David Tolnay324437a2020-03-01 13:02:24 -0800149 Box &operator=(const Box &other) {
David Tolnay7db73692019-10-20 14:51:12 -0400150 if (this != &other) {
David Tolnay33169bd2020-03-06 13:02:08 -0800151 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400152 **this = *other;
153 } else {
154 this->uninit();
David Tolnay33169bd2020-03-06 13:02:08 -0800155 ::new (this->ptr) T(*other);
David Tolnay7db73692019-10-20 14:51:12 -0400156 }
157 }
158 return *this;
159 }
David Tolnay324437a2020-03-01 13:02:24 -0800160 Box &operator=(Box &&other) noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800161 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400162 this->drop();
163 }
David Tolnay33169bd2020-03-06 13:02:08 -0800164 this->ptr = other.ptr;
165 other.ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400166 return *this;
167 }
David Tolnay324437a2020-03-01 13:02:24 -0800168 ~Box() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800169 if (this->ptr) {
David Tolnay7db73692019-10-20 14:51:12 -0400170 this->drop();
171 }
172 }
173
David Tolnay33169bd2020-03-06 13:02:08 -0800174 const T *operator->() const noexcept { return this->ptr; }
175 const T &operator*() const noexcept { return *this->ptr; }
176 T *operator->() noexcept { return this->ptr; }
177 T &operator*() noexcept { return *this->ptr; }
David Tolnay7db73692019-10-20 14:51:12 -0400178
David Tolnayf262d382020-04-11 22:12:40 -0700179 template <typename... Fields>
180 static Box in_place(Fields &&... fields) {
David Tolnay7ce59fc2020-04-11 11:46:33 -0700181 Box box;
182 box.uninit();
183 ::new (box.ptr) T{std::forward<Fields>(fields)...};
184 return box;
185 }
186
David Tolnay7db73692019-10-20 14:51:12 -0400187 // Important: requires that `raw` came from an into_raw call. Do not pass a
188 // pointer from `new` or any other source.
David Tolnay324437a2020-03-01 13:02:24 -0800189 static Box from_raw(T *raw) noexcept {
190 Box box;
David Tolnay33169bd2020-03-06 13:02:08 -0800191 box.ptr = raw;
David Tolnay7db73692019-10-20 14:51:12 -0400192 return box;
193 }
194
195 T *into_raw() noexcept {
David Tolnay33169bd2020-03-06 13:02:08 -0800196 T *raw = this->ptr;
197 this->ptr = nullptr;
David Tolnay7db73692019-10-20 14:51:12 -0400198 return raw;
199 }
200
201private:
David Tolnay324437a2020-03-01 13:02:24 -0800202 Box() noexcept {}
David Tolnay7db73692019-10-20 14:51:12 -0400203 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400204 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800205 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400206};
David Tolnay69601622020-04-29 18:48:36 -0700207#endif // CXXBRIDGE03_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400208
David Tolnay69601622020-04-29 18:48:36 -0700209#ifndef CXXBRIDGE03_RUST_VEC
210#define CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700211template <typename T>
212class Vec final {
213public:
David Tolnayc87c2152020-04-24 17:07:41 -0700214 using value_type = T;
215
David Tolnayf97c2d52020-04-25 16:37:48 -0700216 Vec() noexcept;
217 Vec(Vec &&other) noexcept {
218 this->repr = other.repr;
219 new (&other) Vec();
220 }
David Tolnaycb800572020-04-24 20:30:43 -0700221 ~Vec() noexcept { this->drop(); }
222
David Tolnayf97c2d52020-04-25 16:37:48 -0700223 Vec &operator=(Vec &&other) noexcept {
224 if (this != &other) {
225 this->drop();
226 this->repr = other.repr;
227 new (&other) Vec();
228 }
229 return *this;
230 }
231
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700232 size_t size() const noexcept;
David Tolnay465305b2020-04-24 16:48:18 -0700233 bool empty() const noexcept { return size() == 0; }
David Tolnay219c0792020-04-24 20:31:37 -0700234 const T *data() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700235
David Tolnayc87c2152020-04-24 17:07:41 -0700236 class const_iterator {
237 public:
myronahnda9be502020-04-29 05:47:23 +0700238 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700239 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700240 using pointer =
241 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700242 using reference = typename std::add_lvalue_reference<
243 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700244 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700245
David Tolnay1385ca42020-05-12 20:15:20 -0700246 const T &operator*() const noexcept {
247 return *static_cast<const T *>(this->pos);
248 }
249 const T *operator->() const noexcept {
250 return static_cast<const T *>(this->pos);
251 }
252 const_iterator &operator++() noexcept {
David Tolnayc87c2152020-04-24 17:07:41 -0700253 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
254 return *this;
255 }
David Tolnay1385ca42020-05-12 20:15:20 -0700256 const_iterator operator++(int) noexcept {
myronahnda9be502020-04-29 05:47:23 +0700257 auto ret = const_iterator(*this);
258 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
259 return ret;
260 }
David Tolnay1385ca42020-05-12 20:15:20 -0700261 bool operator==(const const_iterator &other) const noexcept {
David Tolnayc87c2152020-04-24 17:07:41 -0700262 return this->pos == other.pos;
263 }
David Tolnay1385ca42020-05-12 20:15:20 -0700264 bool operator!=(const const_iterator &other) const noexcept {
David Tolnayc87c2152020-04-24 17:07:41 -0700265 return this->pos != other.pos;
266 }
267
268 private:
269 friend class Vec;
270 const void *pos;
271 size_t stride;
272 };
273
274 const_iterator begin() const noexcept {
275 const_iterator it;
276 it.pos = this->data();
277 it.stride = this->stride();
278 return it;
279 }
280 const_iterator end() const noexcept {
281 const_iterator it = this->begin();
282 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
283 return it;
284 }
285
David Tolnay313b10e2020-04-25 16:30:51 -0700286 // Internal API only intended for the cxxbridge code generator.
287 Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
288
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700289private:
David Tolnay503d0192020-04-24 22:18:56 -0700290 static size_t stride() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700291 void drop() noexcept;
292
293 // Size and alignment statically verified by rust_vec.rs.
294 std::array<uintptr_t, 3> repr;
295};
David Tolnay69601622020-04-29 18:48:36 -0700296#endif // CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700297
David Tolnay69601622020-04-29 18:48:36 -0700298#ifndef CXXBRIDGE03_RUST_FN
299#define CXXBRIDGE03_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700300template <typename Signature, bool Throws = false>
301class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700302
303template <typename Ret, typename... Args, bool Throws>
304class Fn<Ret(Args...), Throws> {
305public:
David Tolnay533d4582020-04-08 20:29:14 -0700306 Ret operator()(Args... args) const noexcept(!Throws);
307 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700308
309private:
310 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
311 void *fn;
312};
313
David Tolnayf262d382020-04-11 22:12:40 -0700314template <typename Signature>
315using TryFn = Fn<Signature, true>;
David Tolnay69601622020-04-29 18:48:36 -0700316#endif // CXXBRIDGE03_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700317
David Tolnay69601622020-04-29 18:48:36 -0700318#ifndef CXXBRIDGE03_RUST_ERROR
319#define CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700320class Error final : std::exception {
321public:
322 Error(const Error &);
323 Error(Error &&) noexcept;
324 Error(Str::Repr) noexcept;
325 ~Error() noexcept;
326 const char *what() const noexcept override;
327
328private:
329 Str::Repr msg;
330};
David Tolnay69601622020-04-29 18:48:36 -0700331#endif // CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700332
David Tolnay69601622020-04-29 18:48:36 -0700333#ifndef CXXBRIDGE03_RUST_ISIZE
334#define CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700335#if defined(_WIN32)
336using isize = SSIZE_T;
337#else
338using isize = ssize_t;
339#endif
David Tolnay69601622020-04-29 18:48:36 -0700340#endif // CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700341
David Tolnay851677c2020-03-01 23:49:46 -0800342std::ostream &operator<<(std::ostream &, const String &);
343std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400344
David Tolnay3b0c9882020-03-01 14:08:57 -0800345// Snake case aliases for use in code that uses this style for type names.
346using string = String;
347using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700348template <class T>
349using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700350using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700351template <typename Signature, bool Throws = false>
352using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700353template <typename Signature>
354using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800355
David Tolnay75dca2e2020-03-25 20:17:52 -0700356template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700357Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700358 return (*this->trampoline)(std::move(args)..., this->fn);
359}
360
David Tolnaya23129c2020-04-08 20:08:21 -0700361template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700362Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700363 return *this;
364}
365
David Tolnay69601622020-04-29 18:48:36 -0700366} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800367} // namespace rust