blob: f211b3be1142487e43b14933830d22d0bf7ee9f5 [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 Tolnay0ecd05a2020-07-29 16:32:03 -07007#include <new>
David Tolnay7db73692019-10-20 14:51:12 -04008#include <string>
David Tolnayf6292372020-03-01 21:09:11 -08009#include <type_traits>
David Tolnay4791f1c2020-03-17 21:53:16 -070010#include <utility>
David Tolnay37dd7e12020-04-25 12:51:59 -070011#include <vector>
David Tolnay59b5ba12020-04-10 11:32:19 -070012#if defined(_WIN32)
13#include <BaseTsd.h>
14#endif
David Tolnay7db73692019-10-20 14:51:12 -040015
David Tolnay750755e2020-03-01 13:04:08 -080016namespace rust {
David Tolnay69601622020-04-29 18:48:36 -070017inline namespace cxxbridge03 {
David Tolnay7db73692019-10-20 14:51:12 -040018
David Tolnay2a2b9ad2020-05-12 20:07:26 -070019struct unsafe_bitcopy_t;
David Tolnayd1e2efc2020-03-03 22:25:43 -080020
David Tolnay69601622020-04-29 18:48:36 -070021#ifndef CXXBRIDGE03_RUST_STRING
22#define CXXBRIDGE03_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080023class String final {
David Tolnay7db73692019-10-20 14:51:12 -040024public:
David Tolnay56082162020-03-01 12:57:33 -080025 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080026 String(const String &) noexcept;
27 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080028 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080029
30 String(const std::string &);
31 String(const char *);
32
33 String &operator=(const String &) noexcept;
34 String &operator=(String &&) noexcept;
35
David Tolnay404d6892020-03-01 20:19:41 -080036 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040037
38 // Note: no null terminator.
39 const char *data() const noexcept;
40 size_t size() const noexcept;
41 size_t length() const noexcept;
42
David Tolnayd1e2efc2020-03-03 22:25:43 -080043 // Internal API only intended for the cxxbridge code generator.
44 String(unsafe_bitcopy_t, const String &) noexcept;
45
David Tolnay7db73692019-10-20 14:51:12 -040046private:
47 // Size and alignment statically verified by rust_string.rs.
48 std::array<uintptr_t, 3> repr;
49};
David Tolnay69601622020-04-29 18:48:36 -070050#endif // CXXBRIDGE03_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040051
David Tolnay69601622020-04-29 18:48:36 -070052#ifndef CXXBRIDGE03_RUST_STR
53#define CXXBRIDGE03_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080054class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040055public:
David Tolnay09dbe752020-03-01 13:00:40 -080056 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080057 Str(const Str &) noexcept;
58
David Tolnay851677c2020-03-01 23:49:46 -080059 Str(const std::string &);
60 Str(const char *);
61 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080062
63 Str &operator=(Str) noexcept;
64
David Tolnay404d6892020-03-01 20:19:41 -080065 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040066
67 // Note: no null terminator.
68 const char *data() const noexcept;
69 size_t size() const noexcept;
70 size_t length() const noexcept;
71
72 // Repr is PRIVATE; must not be used other than by our generated code.
73 //
74 // Not necessarily ABI compatible with &str. Codegen will translate to
75 // cxx::rust_str::RustStr which matches this layout.
76 struct Repr {
77 const char *ptr;
78 size_t len;
79 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080080 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080081 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040082
83private:
84 Repr repr;
85};
David Tolnay69601622020-04-29 18:48:36 -070086#endif // CXXBRIDGE03_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040087
David Tolnay69601622020-04-29 18:48:36 -070088#ifndef CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070089template <typename T>
90class Slice final {
91public:
David Tolnay2a2b9ad2020-05-12 20:07:26 -070092 Slice() noexcept;
93 Slice(const Slice<T> &) noexcept;
94 Slice(const T *, size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070095
David Tolnay2a2b9ad2020-05-12 20:07:26 -070096 Slice &operator=(Slice<T>) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070097
David Tolnay2a2b9ad2020-05-12 20:07:26 -070098 const T *data() const noexcept;
99 size_t size() const noexcept;
100 size_t length() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700101
102 // Repr is PRIVATE; must not be used other than by our generated code.
103 //
104 // At present this class is only used for &[u8] slices.
105 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700106 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700107 struct Repr {
108 const T *ptr;
109 size_t len;
110 };
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700111 Slice(Repr) noexcept;
112 explicit operator Repr() noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700113
114private:
115 Repr repr;
116};
David Tolnay69601622020-04-29 18:48:36 -0700117#endif // CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700118
David Tolnay69601622020-04-29 18:48:36 -0700119#ifndef CXXBRIDGE03_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700120template <typename T>
121class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400122public:
David Tolnayf6292372020-03-01 21:09:11 -0800123 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700124 using const_pointer =
125 typename std::add_pointer<typename std::add_const<T>::type>::type;
126 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800127
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700128 Box(const Box &);
129 Box(Box &&) noexcept;
130 ~Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400131
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700132 explicit Box(const T &);
133 explicit Box(T &&);
134
135 Box &operator=(const Box &);
136 Box &operator=(Box &&) noexcept;
137
138 const T *operator->() const noexcept;
139 const T &operator*() const noexcept;
140 T *operator->() noexcept;
141 T &operator*() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400142
David Tolnayf262d382020-04-11 22:12:40 -0700143 template <typename... Fields>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700144 static Box in_place(Fields &&...);
David Tolnay7ce59fc2020-04-11 11:46:33 -0700145
David Tolnay7db73692019-10-20 14:51:12 -0400146 // Important: requires that `raw` came from an into_raw call. Do not pass a
147 // pointer from `new` or any other source.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700148 static Box from_raw(T *) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400149
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700150 T *into_raw() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400151
152private:
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700153 Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400154 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400155 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800156 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400157};
David Tolnay69601622020-04-29 18:48:36 -0700158#endif // CXXBRIDGE03_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400159
David Tolnay69601622020-04-29 18:48:36 -0700160#ifndef CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700161template <typename T>
162class Vec final {
163public:
David Tolnayc87c2152020-04-24 17:07:41 -0700164 using value_type = T;
165
David Tolnayf97c2d52020-04-25 16:37:48 -0700166 Vec() noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700167 Vec(Vec &&) noexcept;
168 ~Vec() noexcept;
David Tolnaycb800572020-04-24 20:30:43 -0700169
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700170 Vec &operator=(Vec &&) noexcept;
David Tolnayf97c2d52020-04-25 16:37:48 -0700171
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700172 size_t size() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700173 bool empty() const noexcept;
David Tolnay219c0792020-04-24 20:31:37 -0700174 const T *data() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700175
David Tolnayc87c2152020-04-24 17:07:41 -0700176 class const_iterator {
177 public:
myronahnda9be502020-04-29 05:47:23 +0700178 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700179 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700180 using pointer =
181 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700182 using reference = typename std::add_lvalue_reference<
183 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700184 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700185
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700186 const T &operator*() const noexcept;
187 const T *operator->() const noexcept;
188 const_iterator &operator++() noexcept;
189 const_iterator operator++(int) noexcept;
190 bool operator==(const const_iterator &) const noexcept;
191 bool operator!=(const const_iterator &) const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700192
193 private:
194 friend class Vec;
195 const void *pos;
196 size_t stride;
197 };
198
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700199 const_iterator begin() const noexcept;
200 const_iterator end() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700201
David Tolnay313b10e2020-04-25 16:30:51 -0700202 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700203 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700204
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700205private:
David Tolnay503d0192020-04-24 22:18:56 -0700206 static size_t stride() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700207 void drop() noexcept;
208
209 // Size and alignment statically verified by rust_vec.rs.
210 std::array<uintptr_t, 3> repr;
211};
David Tolnay69601622020-04-29 18:48:36 -0700212#endif // CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700213
David Tolnay69601622020-04-29 18:48:36 -0700214#ifndef CXXBRIDGE03_RUST_FN
215#define CXXBRIDGE03_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700216template <typename Signature, bool Throws = false>
217class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700218
219template <typename Ret, typename... Args, bool Throws>
220class Fn<Ret(Args...), Throws> {
221public:
David Tolnay533d4582020-04-08 20:29:14 -0700222 Ret operator()(Args... args) const noexcept(!Throws);
223 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700224
225private:
226 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
227 void *fn;
228};
229
David Tolnayf262d382020-04-11 22:12:40 -0700230template <typename Signature>
231using TryFn = Fn<Signature, true>;
David Tolnay69601622020-04-29 18:48:36 -0700232#endif // CXXBRIDGE03_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700233
David Tolnay69601622020-04-29 18:48:36 -0700234#ifndef CXXBRIDGE03_RUST_ERROR
235#define CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700236class Error final : std::exception {
237public:
238 Error(const Error &);
239 Error(Error &&) noexcept;
240 Error(Str::Repr) noexcept;
241 ~Error() noexcept;
242 const char *what() const noexcept override;
243
244private:
245 Str::Repr msg;
246};
David Tolnay69601622020-04-29 18:48:36 -0700247#endif // CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700248
David Tolnay69601622020-04-29 18:48:36 -0700249#ifndef CXXBRIDGE03_RUST_ISIZE
250#define CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700251#if defined(_WIN32)
252using isize = SSIZE_T;
253#else
254using isize = ssize_t;
255#endif
David Tolnay69601622020-04-29 18:48:36 -0700256#endif // CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700257
David Tolnay851677c2020-03-01 23:49:46 -0800258std::ostream &operator<<(std::ostream &, const String &);
259std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400260
David Tolnay3b0c9882020-03-01 14:08:57 -0800261// Snake case aliases for use in code that uses this style for type names.
262using string = String;
263using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700264template <class T>
265using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700266using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700267template <typename Signature, bool Throws = false>
268using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700269template <typename Signature>
270using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800271
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700272
273
274////////////////////////////////////////////////////////////////////////////////
275/// end public API, begin implementation details
276
David Tolnay75dca2e2020-03-25 20:17:52 -0700277template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700278Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700279 return (*this->trampoline)(std::move(args)..., this->fn);
280}
281
David Tolnaya23129c2020-04-08 20:08:21 -0700282template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700283Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700284 return *this;
285}
286
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700287#ifndef CXXBRIDGE03_RUST_BITCOPY
288#define CXXBRIDGE03_RUST_BITCOPY
289struct unsafe_bitcopy_t {
290 explicit unsafe_bitcopy_t() = default;
291};
292
293constexpr unsafe_bitcopy_t unsafe_bitcopy{};
294#endif // CXXBRIDGE03_RUST_BITCOPY
295
296#ifndef CXXBRIDGE03_RUST_SLICE
297#define CXXBRIDGE03_RUST_SLICE
298template <typename T>
299Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
300
301template <typename T>
302Slice<T>::Slice(const Slice<T> &) noexcept = default;
303
304template <typename T>
305Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
306
307template <typename T>
308Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
309 this->repr = other.repr;
310 return *this;
311}
312
313template <typename T>
314const T *Slice<T>::data() const noexcept {
315 return this->repr.ptr;
316}
317
318template <typename T>
319size_t Slice<T>::size() const noexcept {
320 return this->repr.len;
321}
322
323template <typename T>
324size_t Slice<T>::length() const noexcept {
325 return this->repr.len;
326}
327
328template <typename T>
329Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
330
331template <typename T>
332Slice<T>::operator Repr() noexcept {
333 return this->repr;
334}
335#endif // CXXBRIDGE03_RUST_SLICE
336
337#ifndef CXXBRIDGE03_RUST_BOX
338#define CXXBRIDGE03_RUST_BOX
339template <typename T>
340Box<T>::Box(const Box &other) : Box(*other) {}
341
342template <typename T>
343Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
344 other.ptr = nullptr;
345}
346
347template <typename T>
348Box<T>::Box(const T &val) {
349 this->uninit();
350 ::new (this->ptr) T(val);
351}
352
353template <typename T>
354Box<T>::Box(T &&val) {
355 this->uninit();
356 ::new (this->ptr) T(std::move(val));
357}
358
359template <typename T>
360Box<T>::~Box() noexcept {
361 if (this->ptr) {
362 this->drop();
363 }
364}
365
366template <typename T>
367Box<T> &Box<T>::operator=(const Box &other) {
368 if (this != &other) {
369 if (this->ptr) {
370 **this = *other;
371 } else {
372 this->uninit();
373 ::new (this->ptr) T(*other);
374 }
375 }
376 return *this;
377}
378
379template <typename T>
380Box<T> &Box<T>::operator=(Box &&other) noexcept {
381 if (this->ptr) {
382 this->drop();
383 }
384 this->ptr = other.ptr;
385 other.ptr = nullptr;
386 return *this;
387}
388
389template <typename T>
390const T *Box<T>::operator->() const noexcept {
391 return this->ptr;
392}
393
394template <typename T>
395const T &Box<T>::operator*() const noexcept {
396 return *this->ptr;
397}
398
399template <typename T>
400T *Box<T>::operator->() noexcept {
401 return this->ptr;
402}
403
404template <typename T>
405T &Box<T>::operator*() noexcept {
406 return *this->ptr;
407}
408
409template <typename T>
410template <typename... Fields>
411Box<T> Box<T>::in_place(Fields &&... fields) {
412 Box box;
413 box.uninit();
414 ::new (box.ptr) T{std::forward<Fields>(fields)...};
415 return box;
416}
417
418template <typename T>
419Box<T> Box<T>::from_raw(T *raw) noexcept {
420 Box box;
421 box.ptr = raw;
422 return box;
423}
424
425template <typename T>
426T *Box<T>::into_raw() noexcept {
427 T *raw = this->ptr;
428 this->ptr = nullptr;
429 return raw;
430}
431
432template <typename T>
433Box<T>::Box() noexcept {}
434#endif // CXXBRIDGE03_RUST_BOX
435
436#ifndef CXXBRIDGE03_RUST_VEC
437#define CXXBRIDGE03_RUST_VEC
438template <typename T>
439Vec<T>::Vec(Vec &&other) noexcept {
440 this->repr = other.repr;
441 new (&other) Vec();
442}
443
444template <typename T>
445Vec<T>::~Vec() noexcept {
446 this->drop();
447}
448
449template <typename T>
450Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
451 if (this != &other) {
452 this->drop();
453 this->repr = other.repr;
454 new (&other) Vec();
455 }
456 return *this;
457}
458
459template <typename T>
460bool Vec<T>::empty() const noexcept {
461 return size() == 0;
462}
463
464template <typename T>
465const T &Vec<T>::const_iterator::operator*() const noexcept {
466 return *static_cast<const T *>(this->pos);
467}
468
469template <typename T>
470const T *Vec<T>::const_iterator::operator->() const noexcept {
471 return static_cast<const T *>(this->pos);
472}
473
474template <typename T>
475typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
476 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
477 return *this;
478}
479
480template <typename T>
481typename Vec<T>::const_iterator
482Vec<T>::const_iterator::operator++(int) noexcept {
483 auto ret = const_iterator(*this);
484 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
485 return ret;
486}
487
488template <typename T>
489bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
490 noexcept {
491 return this->pos == other.pos;
492}
493
494template <typename T>
495bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
496 noexcept {
497 return this->pos != other.pos;
498}
499
500template <typename T>
501typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
502 const_iterator it;
503 it.pos = this->data();
504 it.stride = this->stride();
505 return it;
506}
507
508template <typename T>
509typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
510 const_iterator it = this->begin();
511 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
512 return it;
513}
514
515// Internal API only intended for the cxxbridge code generator.
516template <typename T>
517Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
518#endif // CXXBRIDGE03_RUST_VEC
519
David Tolnay69601622020-04-29 18:48:36 -0700520} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800521} // namespace rust