blob: 5a33a7a46706be111dc8fe7f34215e8ef0490ae5 [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 *);
David Tolnayc2bbd952020-07-29 18:15:26 -070032 String(const char *, size_t);
David Tolnayd9c4ac92020-03-01 20:33:58 -080033
34 String &operator=(const String &) noexcept;
35 String &operator=(String &&) noexcept;
36
David Tolnay404d6892020-03-01 20:19:41 -080037 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040038
39 // Note: no null terminator.
40 const char *data() const noexcept;
41 size_t size() const noexcept;
42 size_t length() const noexcept;
43
David Tolnayd1e2efc2020-03-03 22:25:43 -080044 // Internal API only intended for the cxxbridge code generator.
45 String(unsafe_bitcopy_t, const String &) noexcept;
46
David Tolnay7db73692019-10-20 14:51:12 -040047private:
48 // Size and alignment statically verified by rust_string.rs.
49 std::array<uintptr_t, 3> repr;
50};
David Tolnay69601622020-04-29 18:48:36 -070051#endif // CXXBRIDGE03_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040052
David Tolnay69601622020-04-29 18:48:36 -070053#ifndef CXXBRIDGE03_RUST_STR
54#define CXXBRIDGE03_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080055class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040056public:
David Tolnay09dbe752020-03-01 13:00:40 -080057 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080058 Str(const Str &) noexcept;
59
David Tolnay851677c2020-03-01 23:49:46 -080060 Str(const std::string &);
61 Str(const char *);
62 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080063
64 Str &operator=(Str) noexcept;
65
David Tolnay404d6892020-03-01 20:19:41 -080066 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040067
68 // Note: no null terminator.
69 const char *data() const noexcept;
70 size_t size() const noexcept;
71 size_t length() const noexcept;
72
73 // Repr is PRIVATE; must not be used other than by our generated code.
74 //
75 // Not necessarily ABI compatible with &str. Codegen will translate to
76 // cxx::rust_str::RustStr which matches this layout.
77 struct Repr {
78 const char *ptr;
79 size_t len;
80 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080081 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080082 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040083
84private:
85 Repr repr;
86};
David Tolnay69601622020-04-29 18:48:36 -070087#endif // CXXBRIDGE03_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040088
David Tolnay69601622020-04-29 18:48:36 -070089#ifndef CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070090template <typename T>
91class Slice final {
92public:
David Tolnay2a2b9ad2020-05-12 20:07:26 -070093 Slice() noexcept;
94 Slice(const Slice<T> &) noexcept;
95 Slice(const T *, size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070096
David Tolnay2a2b9ad2020-05-12 20:07:26 -070097 Slice &operator=(Slice<T>) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070098
David Tolnay2a2b9ad2020-05-12 20:07:26 -070099 const T *data() const noexcept;
100 size_t size() const noexcept;
101 size_t length() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700102
103 // Repr is PRIVATE; must not be used other than by our generated code.
104 //
105 // At present this class is only used for &[u8] slices.
106 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700107 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700108 struct Repr {
109 const T *ptr;
110 size_t len;
111 };
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700112 Slice(Repr) noexcept;
113 explicit operator Repr() noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700114
115private:
116 Repr repr;
117};
David Tolnay69601622020-04-29 18:48:36 -0700118#endif // CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700119
David Tolnay69601622020-04-29 18:48:36 -0700120#ifndef CXXBRIDGE03_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700121template <typename T>
122class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400123public:
David Tolnayf6292372020-03-01 21:09:11 -0800124 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700125 using const_pointer =
126 typename std::add_pointer<typename std::add_const<T>::type>::type;
127 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800128
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700129 Box(const Box &);
130 Box(Box &&) noexcept;
131 ~Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400132
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700133 explicit Box(const T &);
134 explicit Box(T &&);
135
136 Box &operator=(const Box &);
137 Box &operator=(Box &&) noexcept;
138
139 const T *operator->() const noexcept;
140 const T &operator*() const noexcept;
141 T *operator->() noexcept;
142 T &operator*() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400143
David Tolnayf262d382020-04-11 22:12:40 -0700144 template <typename... Fields>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700145 static Box in_place(Fields &&...);
David Tolnay7ce59fc2020-04-11 11:46:33 -0700146
David Tolnay7db73692019-10-20 14:51:12 -0400147 // Important: requires that `raw` came from an into_raw call. Do not pass a
148 // pointer from `new` or any other source.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700149 static Box from_raw(T *) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400150
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700151 T *into_raw() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400152
153private:
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700154 Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400155 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400156 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800157 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400158};
David Tolnay69601622020-04-29 18:48:36 -0700159#endif // CXXBRIDGE03_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400160
David Tolnay69601622020-04-29 18:48:36 -0700161#ifndef CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700162template <typename T>
163class Vec final {
164public:
David Tolnayc87c2152020-04-24 17:07:41 -0700165 using value_type = T;
166
David Tolnayf97c2d52020-04-25 16:37:48 -0700167 Vec() noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700168 Vec(Vec &&) noexcept;
169 ~Vec() noexcept;
David Tolnaycb800572020-04-24 20:30:43 -0700170
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700171 Vec &operator=(Vec &&) noexcept;
David Tolnayf97c2d52020-04-25 16:37:48 -0700172
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700173 size_t size() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700174 bool empty() const noexcept;
David Tolnay219c0792020-04-24 20:31:37 -0700175 const T *data() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700176
David Tolnayc87c2152020-04-24 17:07:41 -0700177 class const_iterator {
178 public:
myronahnda9be502020-04-29 05:47:23 +0700179 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700180 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700181 using pointer =
182 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700183 using reference = typename std::add_lvalue_reference<
184 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700185 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700186
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700187 const T &operator*() const noexcept;
188 const T *operator->() const noexcept;
189 const_iterator &operator++() noexcept;
190 const_iterator operator++(int) noexcept;
191 bool operator==(const const_iterator &) const noexcept;
192 bool operator!=(const const_iterator &) const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700193
194 private:
195 friend class Vec;
196 const void *pos;
197 size_t stride;
198 };
199
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700200 const_iterator begin() const noexcept;
201 const_iterator end() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700202
David Tolnay313b10e2020-04-25 16:30:51 -0700203 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700204 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700205
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700206private:
David Tolnay503d0192020-04-24 22:18:56 -0700207 static size_t stride() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700208 void drop() noexcept;
209
210 // Size and alignment statically verified by rust_vec.rs.
211 std::array<uintptr_t, 3> repr;
212};
David Tolnay69601622020-04-29 18:48:36 -0700213#endif // CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700214
David Tolnay69601622020-04-29 18:48:36 -0700215#ifndef CXXBRIDGE03_RUST_FN
216#define CXXBRIDGE03_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700217template <typename Signature, bool Throws = false>
218class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700219
220template <typename Ret, typename... Args, bool Throws>
221class Fn<Ret(Args...), Throws> {
222public:
David Tolnay533d4582020-04-08 20:29:14 -0700223 Ret operator()(Args... args) const noexcept(!Throws);
224 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700225
226private:
227 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
228 void *fn;
229};
230
David Tolnayf262d382020-04-11 22:12:40 -0700231template <typename Signature>
232using TryFn = Fn<Signature, true>;
David Tolnay69601622020-04-29 18:48:36 -0700233#endif // CXXBRIDGE03_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700234
David Tolnay69601622020-04-29 18:48:36 -0700235#ifndef CXXBRIDGE03_RUST_ERROR
236#define CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700237class Error final : std::exception {
238public:
239 Error(const Error &);
240 Error(Error &&) noexcept;
241 Error(Str::Repr) noexcept;
242 ~Error() noexcept;
243 const char *what() const noexcept override;
244
245private:
246 Str::Repr msg;
247};
David Tolnay69601622020-04-29 18:48:36 -0700248#endif // CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700249
David Tolnay69601622020-04-29 18:48:36 -0700250#ifndef CXXBRIDGE03_RUST_ISIZE
251#define CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700252#if defined(_WIN32)
253using isize = SSIZE_T;
254#else
255using isize = ssize_t;
256#endif
David Tolnay69601622020-04-29 18:48:36 -0700257#endif // CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700258
David Tolnay851677c2020-03-01 23:49:46 -0800259std::ostream &operator<<(std::ostream &, const String &);
260std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400261
David Tolnay3b0c9882020-03-01 14:08:57 -0800262// Snake case aliases for use in code that uses this style for type names.
263using string = String;
264using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700265template <class T>
266using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700267using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700268template <typename Signature, bool Throws = false>
269using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700270template <typename Signature>
271using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800272
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700273
274
275////////////////////////////////////////////////////////////////////////////////
276/// end public API, begin implementation details
277
David Tolnay75dca2e2020-03-25 20:17:52 -0700278template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700279Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700280 return (*this->trampoline)(std::move(args)..., this->fn);
281}
282
David Tolnaya23129c2020-04-08 20:08:21 -0700283template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700284Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700285 return *this;
286}
287
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700288#ifndef CXXBRIDGE03_RUST_BITCOPY
289#define CXXBRIDGE03_RUST_BITCOPY
290struct unsafe_bitcopy_t {
291 explicit unsafe_bitcopy_t() = default;
292};
293
294constexpr unsafe_bitcopy_t unsafe_bitcopy{};
295#endif // CXXBRIDGE03_RUST_BITCOPY
296
297#ifndef CXXBRIDGE03_RUST_SLICE
298#define CXXBRIDGE03_RUST_SLICE
299template <typename T>
300Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
301
302template <typename T>
303Slice<T>::Slice(const Slice<T> &) noexcept = default;
304
305template <typename T>
306Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
307
308template <typename T>
309Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
310 this->repr = other.repr;
311 return *this;
312}
313
314template <typename T>
315const T *Slice<T>::data() const noexcept {
316 return this->repr.ptr;
317}
318
319template <typename T>
320size_t Slice<T>::size() const noexcept {
321 return this->repr.len;
322}
323
324template <typename T>
325size_t Slice<T>::length() const noexcept {
326 return this->repr.len;
327}
328
329template <typename T>
330Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
331
332template <typename T>
333Slice<T>::operator Repr() noexcept {
334 return this->repr;
335}
336#endif // CXXBRIDGE03_RUST_SLICE
337
338#ifndef CXXBRIDGE03_RUST_BOX
339#define CXXBRIDGE03_RUST_BOX
340template <typename T>
341Box<T>::Box(const Box &other) : Box(*other) {}
342
343template <typename T>
344Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
345 other.ptr = nullptr;
346}
347
348template <typename T>
349Box<T>::Box(const T &val) {
350 this->uninit();
351 ::new (this->ptr) T(val);
352}
353
354template <typename T>
355Box<T>::Box(T &&val) {
356 this->uninit();
357 ::new (this->ptr) T(std::move(val));
358}
359
360template <typename T>
361Box<T>::~Box() noexcept {
362 if (this->ptr) {
363 this->drop();
364 }
365}
366
367template <typename T>
368Box<T> &Box<T>::operator=(const Box &other) {
369 if (this != &other) {
370 if (this->ptr) {
371 **this = *other;
372 } else {
373 this->uninit();
374 ::new (this->ptr) T(*other);
375 }
376 }
377 return *this;
378}
379
380template <typename T>
381Box<T> &Box<T>::operator=(Box &&other) noexcept {
382 if (this->ptr) {
383 this->drop();
384 }
385 this->ptr = other.ptr;
386 other.ptr = nullptr;
387 return *this;
388}
389
390template <typename T>
391const T *Box<T>::operator->() const noexcept {
392 return this->ptr;
393}
394
395template <typename T>
396const T &Box<T>::operator*() const noexcept {
397 return *this->ptr;
398}
399
400template <typename T>
401T *Box<T>::operator->() noexcept {
402 return this->ptr;
403}
404
405template <typename T>
406T &Box<T>::operator*() noexcept {
407 return *this->ptr;
408}
409
410template <typename T>
411template <typename... Fields>
412Box<T> Box<T>::in_place(Fields &&... fields) {
413 Box box;
414 box.uninit();
415 ::new (box.ptr) T{std::forward<Fields>(fields)...};
416 return box;
417}
418
419template <typename T>
420Box<T> Box<T>::from_raw(T *raw) noexcept {
421 Box box;
422 box.ptr = raw;
423 return box;
424}
425
426template <typename T>
427T *Box<T>::into_raw() noexcept {
428 T *raw = this->ptr;
429 this->ptr = nullptr;
430 return raw;
431}
432
433template <typename T>
434Box<T>::Box() noexcept {}
435#endif // CXXBRIDGE03_RUST_BOX
436
437#ifndef CXXBRIDGE03_RUST_VEC
438#define CXXBRIDGE03_RUST_VEC
439template <typename T>
440Vec<T>::Vec(Vec &&other) noexcept {
441 this->repr = other.repr;
442 new (&other) Vec();
443}
444
445template <typename T>
446Vec<T>::~Vec() noexcept {
447 this->drop();
448}
449
450template <typename T>
451Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
452 if (this != &other) {
453 this->drop();
454 this->repr = other.repr;
455 new (&other) Vec();
456 }
457 return *this;
458}
459
460template <typename T>
461bool Vec<T>::empty() const noexcept {
462 return size() == 0;
463}
464
465template <typename T>
466const T &Vec<T>::const_iterator::operator*() const noexcept {
467 return *static_cast<const T *>(this->pos);
468}
469
470template <typename T>
471const T *Vec<T>::const_iterator::operator->() const noexcept {
472 return static_cast<const T *>(this->pos);
473}
474
475template <typename T>
476typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
477 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
478 return *this;
479}
480
481template <typename T>
482typename Vec<T>::const_iterator
483Vec<T>::const_iterator::operator++(int) noexcept {
484 auto ret = const_iterator(*this);
485 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
486 return ret;
487}
488
489template <typename T>
490bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
491 noexcept {
492 return this->pos == other.pos;
493}
494
495template <typename T>
496bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
497 noexcept {
498 return this->pos != other.pos;
499}
500
501template <typename T>
502typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
503 const_iterator it;
504 it.pos = this->data();
505 it.stride = this->stride();
506 return it;
507}
508
509template <typename T>
510typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
511 const_iterator it = this->begin();
512 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
513 return it;
514}
515
516// Internal API only intended for the cxxbridge code generator.
517template <typename T>
518Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
519#endif // CXXBRIDGE03_RUST_VEC
520
David Tolnay69601622020-04-29 18:48:36 -0700521} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800522} // namespace rust