blob: c3231fd0d11e657f6d7ce513b420de24d295d06a [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 *);
David Tolnay894c5e42020-07-29 18:20:00 -070062 Str(const char *, size_t);
David Tolnay851677c2020-03-01 23:49:46 -080063 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080064
65 Str &operator=(Str) noexcept;
66
David Tolnay404d6892020-03-01 20:19:41 -080067 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040068
69 // Note: no null terminator.
70 const char *data() const noexcept;
71 size_t size() const noexcept;
72 size_t length() const noexcept;
73
74 // Repr is PRIVATE; must not be used other than by our generated code.
75 //
76 // Not necessarily ABI compatible with &str. Codegen will translate to
77 // cxx::rust_str::RustStr which matches this layout.
78 struct Repr {
79 const char *ptr;
80 size_t len;
81 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080082 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080083 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040084
85private:
86 Repr repr;
87};
David Tolnay69601622020-04-29 18:48:36 -070088#endif // CXXBRIDGE03_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040089
David Tolnay69601622020-04-29 18:48:36 -070090#ifndef CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070091template <typename T>
92class Slice final {
93public:
David Tolnay2a2b9ad2020-05-12 20:07:26 -070094 Slice() noexcept;
95 Slice(const Slice<T> &) noexcept;
96 Slice(const T *, size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070097
David Tolnay2a2b9ad2020-05-12 20:07:26 -070098 Slice &operator=(Slice<T>) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070099
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700100 const T *data() const noexcept;
101 size_t size() const noexcept;
102 size_t length() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700103
104 // Repr is PRIVATE; must not be used other than by our generated code.
105 //
106 // At present this class is only used for &[u8] slices.
107 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700108 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700109 struct Repr {
110 const T *ptr;
111 size_t len;
112 };
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700113 Slice(Repr) noexcept;
114 explicit operator Repr() noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700115
116private:
117 Repr repr;
118};
David Tolnay69601622020-04-29 18:48:36 -0700119#endif // CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700120
David Tolnay69601622020-04-29 18:48:36 -0700121#ifndef CXXBRIDGE03_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700122template <typename T>
123class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400124public:
David Tolnayf6292372020-03-01 21:09:11 -0800125 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700126 using const_pointer =
127 typename std::add_pointer<typename std::add_const<T>::type>::type;
128 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800129
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700130 Box(const Box &);
131 Box(Box &&) noexcept;
132 ~Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400133
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700134 explicit Box(const T &);
135 explicit Box(T &&);
136
137 Box &operator=(const Box &);
138 Box &operator=(Box &&) noexcept;
139
140 const T *operator->() const noexcept;
141 const T &operator*() const noexcept;
142 T *operator->() noexcept;
143 T &operator*() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400144
David Tolnayf262d382020-04-11 22:12:40 -0700145 template <typename... Fields>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700146 static Box in_place(Fields &&...);
David Tolnay7ce59fc2020-04-11 11:46:33 -0700147
David Tolnay7db73692019-10-20 14:51:12 -0400148 // Important: requires that `raw` came from an into_raw call. Do not pass a
149 // pointer from `new` or any other source.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700150 static Box from_raw(T *) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400151
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700152 T *into_raw() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400153
154private:
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700155 Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400156 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400157 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800158 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400159};
David Tolnay69601622020-04-29 18:48:36 -0700160#endif // CXXBRIDGE03_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400161
David Tolnay69601622020-04-29 18:48:36 -0700162#ifndef CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700163template <typename T>
164class Vec final {
165public:
David Tolnayc87c2152020-04-24 17:07:41 -0700166 using value_type = T;
167
David Tolnayf97c2d52020-04-25 16:37:48 -0700168 Vec() noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700169 Vec(Vec &&) noexcept;
170 ~Vec() noexcept;
David Tolnaycb800572020-04-24 20:30:43 -0700171
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700172 Vec &operator=(Vec &&) noexcept;
David Tolnayf97c2d52020-04-25 16:37:48 -0700173
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700174 size_t size() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700175 bool empty() const noexcept;
David Tolnay219c0792020-04-24 20:31:37 -0700176 const T *data() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700177
David Tolnayc87c2152020-04-24 17:07:41 -0700178 class const_iterator {
179 public:
myronahnda9be502020-04-29 05:47:23 +0700180 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700181 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700182 using pointer =
183 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700184 using reference = typename std::add_lvalue_reference<
185 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700186 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700187
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700188 const T &operator*() const noexcept;
189 const T *operator->() const noexcept;
190 const_iterator &operator++() noexcept;
191 const_iterator operator++(int) noexcept;
192 bool operator==(const const_iterator &) const noexcept;
193 bool operator!=(const const_iterator &) const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700194
195 private:
196 friend class Vec;
197 const void *pos;
198 size_t stride;
199 };
200
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700201 const_iterator begin() const noexcept;
202 const_iterator end() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700203
David Tolnay313b10e2020-04-25 16:30:51 -0700204 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700205 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700206
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700207private:
David Tolnay503d0192020-04-24 22:18:56 -0700208 static size_t stride() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700209 void drop() noexcept;
210
211 // Size and alignment statically verified by rust_vec.rs.
212 std::array<uintptr_t, 3> repr;
213};
David Tolnay69601622020-04-29 18:48:36 -0700214#endif // CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700215
David Tolnay69601622020-04-29 18:48:36 -0700216#ifndef CXXBRIDGE03_RUST_FN
217#define CXXBRIDGE03_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700218template <typename Signature, bool Throws = false>
219class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700220
221template <typename Ret, typename... Args, bool Throws>
222class Fn<Ret(Args...), Throws> {
223public:
David Tolnay533d4582020-04-08 20:29:14 -0700224 Ret operator()(Args... args) const noexcept(!Throws);
225 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700226
227private:
228 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
229 void *fn;
230};
231
David Tolnayf262d382020-04-11 22:12:40 -0700232template <typename Signature>
233using TryFn = Fn<Signature, true>;
David Tolnay69601622020-04-29 18:48:36 -0700234#endif // CXXBRIDGE03_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700235
David Tolnay69601622020-04-29 18:48:36 -0700236#ifndef CXXBRIDGE03_RUST_ERROR
237#define CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700238class Error final : std::exception {
239public:
240 Error(const Error &);
241 Error(Error &&) noexcept;
242 Error(Str::Repr) noexcept;
243 ~Error() noexcept;
244 const char *what() const noexcept override;
245
246private:
247 Str::Repr msg;
248};
David Tolnay69601622020-04-29 18:48:36 -0700249#endif // CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700250
David Tolnay69601622020-04-29 18:48:36 -0700251#ifndef CXXBRIDGE03_RUST_ISIZE
252#define CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700253#if defined(_WIN32)
254using isize = SSIZE_T;
255#else
256using isize = ssize_t;
257#endif
David Tolnay69601622020-04-29 18:48:36 -0700258#endif // CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700259
David Tolnay851677c2020-03-01 23:49:46 -0800260std::ostream &operator<<(std::ostream &, const String &);
261std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400262
David Tolnay3b0c9882020-03-01 14:08:57 -0800263// Snake case aliases for use in code that uses this style for type names.
264using string = String;
265using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700266template <class T>
267using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700268using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700269template <typename Signature, bool Throws = false>
270using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700271template <typename Signature>
272using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800273
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700274
275
276////////////////////////////////////////////////////////////////////////////////
277/// end public API, begin implementation details
278
David Tolnay75dca2e2020-03-25 20:17:52 -0700279template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700280Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700281 return (*this->trampoline)(std::move(args)..., this->fn);
282}
283
David Tolnaya23129c2020-04-08 20:08:21 -0700284template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700285Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700286 return *this;
287}
288
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700289#ifndef CXXBRIDGE03_RUST_BITCOPY
290#define CXXBRIDGE03_RUST_BITCOPY
291struct unsafe_bitcopy_t {
292 explicit unsafe_bitcopy_t() = default;
293};
294
295constexpr unsafe_bitcopy_t unsafe_bitcopy{};
296#endif // CXXBRIDGE03_RUST_BITCOPY
297
298#ifndef CXXBRIDGE03_RUST_SLICE
299#define CXXBRIDGE03_RUST_SLICE
300template <typename T>
301Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
302
303template <typename T>
304Slice<T>::Slice(const Slice<T> &) noexcept = default;
305
306template <typename T>
307Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
308
309template <typename T>
310Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
311 this->repr = other.repr;
312 return *this;
313}
314
315template <typename T>
316const T *Slice<T>::data() const noexcept {
317 return this->repr.ptr;
318}
319
320template <typename T>
321size_t Slice<T>::size() const noexcept {
322 return this->repr.len;
323}
324
325template <typename T>
326size_t Slice<T>::length() const noexcept {
327 return this->repr.len;
328}
329
330template <typename T>
331Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
332
333template <typename T>
334Slice<T>::operator Repr() noexcept {
335 return this->repr;
336}
337#endif // CXXBRIDGE03_RUST_SLICE
338
339#ifndef CXXBRIDGE03_RUST_BOX
340#define CXXBRIDGE03_RUST_BOX
341template <typename T>
342Box<T>::Box(const Box &other) : Box(*other) {}
343
344template <typename T>
345Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
346 other.ptr = nullptr;
347}
348
349template <typename T>
350Box<T>::Box(const T &val) {
351 this->uninit();
352 ::new (this->ptr) T(val);
353}
354
355template <typename T>
356Box<T>::Box(T &&val) {
357 this->uninit();
358 ::new (this->ptr) T(std::move(val));
359}
360
361template <typename T>
362Box<T>::~Box() noexcept {
363 if (this->ptr) {
364 this->drop();
365 }
366}
367
368template <typename T>
369Box<T> &Box<T>::operator=(const Box &other) {
370 if (this != &other) {
371 if (this->ptr) {
372 **this = *other;
373 } else {
374 this->uninit();
375 ::new (this->ptr) T(*other);
376 }
377 }
378 return *this;
379}
380
381template <typename T>
382Box<T> &Box<T>::operator=(Box &&other) noexcept {
383 if (this->ptr) {
384 this->drop();
385 }
386 this->ptr = other.ptr;
387 other.ptr = nullptr;
388 return *this;
389}
390
391template <typename T>
392const T *Box<T>::operator->() const noexcept {
393 return this->ptr;
394}
395
396template <typename T>
397const T &Box<T>::operator*() const noexcept {
398 return *this->ptr;
399}
400
401template <typename T>
402T *Box<T>::operator->() noexcept {
403 return this->ptr;
404}
405
406template <typename T>
407T &Box<T>::operator*() noexcept {
408 return *this->ptr;
409}
410
411template <typename T>
412template <typename... Fields>
413Box<T> Box<T>::in_place(Fields &&... fields) {
414 Box box;
415 box.uninit();
416 ::new (box.ptr) T{std::forward<Fields>(fields)...};
417 return box;
418}
419
420template <typename T>
421Box<T> Box<T>::from_raw(T *raw) noexcept {
422 Box box;
423 box.ptr = raw;
424 return box;
425}
426
427template <typename T>
428T *Box<T>::into_raw() noexcept {
429 T *raw = this->ptr;
430 this->ptr = nullptr;
431 return raw;
432}
433
434template <typename T>
435Box<T>::Box() noexcept {}
436#endif // CXXBRIDGE03_RUST_BOX
437
438#ifndef CXXBRIDGE03_RUST_VEC
439#define CXXBRIDGE03_RUST_VEC
440template <typename T>
441Vec<T>::Vec(Vec &&other) noexcept {
442 this->repr = other.repr;
443 new (&other) Vec();
444}
445
446template <typename T>
447Vec<T>::~Vec() noexcept {
448 this->drop();
449}
450
451template <typename T>
452Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
453 if (this != &other) {
454 this->drop();
455 this->repr = other.repr;
456 new (&other) Vec();
457 }
458 return *this;
459}
460
461template <typename T>
462bool Vec<T>::empty() const noexcept {
463 return size() == 0;
464}
465
466template <typename T>
467const T &Vec<T>::const_iterator::operator*() const noexcept {
468 return *static_cast<const T *>(this->pos);
469}
470
471template <typename T>
472const T *Vec<T>::const_iterator::operator->() const noexcept {
473 return static_cast<const T *>(this->pos);
474}
475
476template <typename T>
477typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
478 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
479 return *this;
480}
481
482template <typename T>
483typename Vec<T>::const_iterator
484Vec<T>::const_iterator::operator++(int) noexcept {
485 auto ret = const_iterator(*this);
486 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
487 return ret;
488}
489
490template <typename T>
491bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
492 noexcept {
493 return this->pos == other.pos;
494}
495
496template <typename T>
497bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
498 noexcept {
499 return this->pos != other.pos;
500}
501
502template <typename T>
503typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
504 const_iterator it;
505 it.pos = this->data();
506 it.stride = this->stride();
507 return it;
508}
509
510template <typename T>
511typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
512 const_iterator it = this->begin();
513 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
514 return it;
515}
516
517// Internal API only intended for the cxxbridge code generator.
518template <typename T>
519Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
520#endif // CXXBRIDGE03_RUST_VEC
521
David Tolnay69601622020-04-29 18:48:36 -0700522} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800523} // namespace rust