blob: 9f4fb4767a88b50b1e1909716515bfce588dd45b [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 Tolnay2a2b9ad2020-05-12 20:07:26 -070018struct unsafe_bitcopy_t;
David Tolnayd1e2efc2020-03-03 22:25:43 -080019
David Tolnay69601622020-04-29 18:48:36 -070020#ifndef CXXBRIDGE03_RUST_STRING
21#define CXXBRIDGE03_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080022class String final {
David Tolnay7db73692019-10-20 14:51:12 -040023public:
David Tolnay56082162020-03-01 12:57:33 -080024 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080025 String(const String &) noexcept;
26 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080027 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080028
29 String(const std::string &);
30 String(const char *);
31
32 String &operator=(const String &) noexcept;
33 String &operator=(String &&) noexcept;
34
David Tolnay404d6892020-03-01 20:19:41 -080035 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040036
37 // Note: no null terminator.
38 const char *data() const noexcept;
39 size_t size() const noexcept;
40 size_t length() const noexcept;
41
David Tolnayd1e2efc2020-03-03 22:25:43 -080042 // Internal API only intended for the cxxbridge code generator.
43 String(unsafe_bitcopy_t, const String &) noexcept;
44
David Tolnay7db73692019-10-20 14:51:12 -040045private:
46 // Size and alignment statically verified by rust_string.rs.
47 std::array<uintptr_t, 3> repr;
48};
David Tolnay69601622020-04-29 18:48:36 -070049#endif // CXXBRIDGE03_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040050
David Tolnay69601622020-04-29 18:48:36 -070051#ifndef CXXBRIDGE03_RUST_STR
52#define CXXBRIDGE03_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080053class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040054public:
David Tolnay09dbe752020-03-01 13:00:40 -080055 Str() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080056 Str(const Str &) noexcept;
57
David Tolnay851677c2020-03-01 23:49:46 -080058 Str(const std::string &);
59 Str(const char *);
60 Str(std::string &&) = delete;
David Tolnayd9c4ac92020-03-01 20:33:58 -080061
62 Str &operator=(Str) noexcept;
63
David Tolnay404d6892020-03-01 20:19:41 -080064 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040065
66 // Note: no null terminator.
67 const char *data() const noexcept;
68 size_t size() const noexcept;
69 size_t length() const noexcept;
70
71 // Repr is PRIVATE; must not be used other than by our generated code.
72 //
73 // Not necessarily ABI compatible with &str. Codegen will translate to
74 // cxx::rust_str::RustStr which matches this layout.
75 struct Repr {
76 const char *ptr;
77 size_t len;
78 };
David Tolnayd9c4ac92020-03-01 20:33:58 -080079 Str(Repr) noexcept;
David Tolnaybaae4432020-03-01 20:20:10 -080080 explicit operator Repr() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040081
82private:
83 Repr repr;
84};
David Tolnay69601622020-04-29 18:48:36 -070085#endif // CXXBRIDGE03_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040086
David Tolnay69601622020-04-29 18:48:36 -070087#ifndef CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070088template <typename T>
89class Slice final {
90public:
David Tolnay2a2b9ad2020-05-12 20:07:26 -070091 Slice() noexcept;
92 Slice(const Slice<T> &) noexcept;
93 Slice(const T *, size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070094
David Tolnay2a2b9ad2020-05-12 20:07:26 -070095 Slice &operator=(Slice<T>) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070096
David Tolnay2a2b9ad2020-05-12 20:07:26 -070097 const T *data() const noexcept;
98 size_t size() const noexcept;
99 size_t length() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700100
101 // Repr is PRIVATE; must not be used other than by our generated code.
102 //
103 // At present this class is only used for &[u8] slices.
104 // Not necessarily ABI compatible with &[u8]. Codegen will translate to
David Tolnaye710af12020-04-14 16:31:54 -0700105 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayefe81052020-04-14 16:28:24 -0700106 struct Repr {
107 const T *ptr;
108 size_t len;
109 };
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700110 Slice(Repr) noexcept;
111 explicit operator Repr() noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700112
113private:
114 Repr repr;
115};
David Tolnay69601622020-04-29 18:48:36 -0700116#endif // CXXBRIDGE03_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700117
David Tolnay69601622020-04-29 18:48:36 -0700118#ifndef CXXBRIDGE03_RUST_BOX
David Tolnayf262d382020-04-11 22:12:40 -0700119template <typename T>
120class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400121public:
David Tolnayf6292372020-03-01 21:09:11 -0800122 using value_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700123 using const_pointer =
124 typename std::add_pointer<typename std::add_const<T>::type>::type;
125 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800126
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700127 Box(const Box &);
128 Box(Box &&) noexcept;
129 ~Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400130
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700131 explicit Box(const T &);
132 explicit Box(T &&);
133
134 Box &operator=(const Box &);
135 Box &operator=(Box &&) noexcept;
136
137 const T *operator->() const noexcept;
138 const T &operator*() const noexcept;
139 T *operator->() noexcept;
140 T &operator*() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400141
David Tolnayf262d382020-04-11 22:12:40 -0700142 template <typename... Fields>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700143 static Box in_place(Fields &&...);
David Tolnay7ce59fc2020-04-11 11:46:33 -0700144
David Tolnay7db73692019-10-20 14:51:12 -0400145 // Important: requires that `raw` came from an into_raw call. Do not pass a
146 // pointer from `new` or any other source.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700147 static Box from_raw(T *) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400148
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700149 T *into_raw() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400150
151private:
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700152 Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400153 void uninit() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400154 void drop() noexcept;
David Tolnay33169bd2020-03-06 13:02:08 -0800155 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400156};
David Tolnay69601622020-04-29 18:48:36 -0700157#endif // CXXBRIDGE03_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400158
David Tolnay69601622020-04-29 18:48:36 -0700159#ifndef CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700160template <typename T>
161class Vec final {
162public:
David Tolnayc87c2152020-04-24 17:07:41 -0700163 using value_type = T;
164
David Tolnayf97c2d52020-04-25 16:37:48 -0700165 Vec() noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700166 Vec(Vec &&) noexcept;
167 ~Vec() noexcept;
David Tolnaycb800572020-04-24 20:30:43 -0700168
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700169 Vec &operator=(Vec &&) noexcept;
David Tolnayf97c2d52020-04-25 16:37:48 -0700170
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700171 size_t size() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700172 bool empty() const noexcept;
David Tolnay219c0792020-04-24 20:31:37 -0700173 const T *data() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700174
David Tolnayc87c2152020-04-24 17:07:41 -0700175 class const_iterator {
176 public:
myronahnda9be502020-04-29 05:47:23 +0700177 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700178 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700179 using pointer =
180 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700181 using reference = typename std::add_lvalue_reference<
182 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700183 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700184
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700185 const T &operator*() const noexcept;
186 const T *operator->() const noexcept;
187 const_iterator &operator++() noexcept;
188 const_iterator operator++(int) noexcept;
189 bool operator==(const const_iterator &) const noexcept;
190 bool operator!=(const const_iterator &) const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700191
192 private:
193 friend class Vec;
194 const void *pos;
195 size_t stride;
196 };
197
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700198 const_iterator begin() const noexcept;
199 const_iterator end() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700200
David Tolnay313b10e2020-04-25 16:30:51 -0700201 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700202 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700203
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700204private:
David Tolnay503d0192020-04-24 22:18:56 -0700205 static size_t stride() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700206 void drop() noexcept;
207
208 // Size and alignment statically verified by rust_vec.rs.
209 std::array<uintptr_t, 3> repr;
210};
David Tolnay69601622020-04-29 18:48:36 -0700211#endif // CXXBRIDGE03_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700212
David Tolnay69601622020-04-29 18:48:36 -0700213#ifndef CXXBRIDGE03_RUST_FN
214#define CXXBRIDGE03_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700215template <typename Signature, bool Throws = false>
216class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700217
218template <typename Ret, typename... Args, bool Throws>
219class Fn<Ret(Args...), Throws> {
220public:
David Tolnay533d4582020-04-08 20:29:14 -0700221 Ret operator()(Args... args) const noexcept(!Throws);
222 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700223
224private:
225 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
226 void *fn;
227};
228
David Tolnayf262d382020-04-11 22:12:40 -0700229template <typename Signature>
230using TryFn = Fn<Signature, true>;
David Tolnay69601622020-04-29 18:48:36 -0700231#endif // CXXBRIDGE03_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700232
David Tolnay69601622020-04-29 18:48:36 -0700233#ifndef CXXBRIDGE03_RUST_ERROR
234#define CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700235class Error final : std::exception {
236public:
237 Error(const Error &);
238 Error(Error &&) noexcept;
239 Error(Str::Repr) noexcept;
240 ~Error() noexcept;
241 const char *what() const noexcept override;
242
243private:
244 Str::Repr msg;
245};
David Tolnay69601622020-04-29 18:48:36 -0700246#endif // CXXBRIDGE03_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700247
David Tolnay69601622020-04-29 18:48:36 -0700248#ifndef CXXBRIDGE03_RUST_ISIZE
249#define CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700250#if defined(_WIN32)
251using isize = SSIZE_T;
252#else
253using isize = ssize_t;
254#endif
David Tolnay69601622020-04-29 18:48:36 -0700255#endif // CXXBRIDGE03_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700256
David Tolnay851677c2020-03-01 23:49:46 -0800257std::ostream &operator<<(std::ostream &, const String &);
258std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400259
David Tolnay3b0c9882020-03-01 14:08:57 -0800260// Snake case aliases for use in code that uses this style for type names.
261using string = String;
262using str = Str;
David Tolnayf262d382020-04-11 22:12:40 -0700263template <class T>
264using box = Box<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700265using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700266template <typename Signature, bool Throws = false>
267using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700268template <typename Signature>
269using try_fn = TryFn<Signature>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800270
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700271
272
273////////////////////////////////////////////////////////////////////////////////
274/// end public API, begin implementation details
275
David Tolnay75dca2e2020-03-25 20:17:52 -0700276template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700277Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700278 return (*this->trampoline)(std::move(args)..., this->fn);
279}
280
David Tolnaya23129c2020-04-08 20:08:21 -0700281template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700282Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700283 return *this;
284}
285
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700286#ifndef CXXBRIDGE03_RUST_BITCOPY
287#define CXXBRIDGE03_RUST_BITCOPY
288struct unsafe_bitcopy_t {
289 explicit unsafe_bitcopy_t() = default;
290};
291
292constexpr unsafe_bitcopy_t unsafe_bitcopy{};
293#endif // CXXBRIDGE03_RUST_BITCOPY
294
295#ifndef CXXBRIDGE03_RUST_SLICE
296#define CXXBRIDGE03_RUST_SLICE
297template <typename T>
298Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
299
300template <typename T>
301Slice<T>::Slice(const Slice<T> &) noexcept = default;
302
303template <typename T>
304Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
305
306template <typename T>
307Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
308 this->repr = other.repr;
309 return *this;
310}
311
312template <typename T>
313const T *Slice<T>::data() const noexcept {
314 return this->repr.ptr;
315}
316
317template <typename T>
318size_t Slice<T>::size() const noexcept {
319 return this->repr.len;
320}
321
322template <typename T>
323size_t Slice<T>::length() const noexcept {
324 return this->repr.len;
325}
326
327template <typename T>
328Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
329
330template <typename T>
331Slice<T>::operator Repr() noexcept {
332 return this->repr;
333}
334#endif // CXXBRIDGE03_RUST_SLICE
335
336#ifndef CXXBRIDGE03_RUST_BOX
337#define CXXBRIDGE03_RUST_BOX
338template <typename T>
339Box<T>::Box(const Box &other) : Box(*other) {}
340
341template <typename T>
342Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
343 other.ptr = nullptr;
344}
345
346template <typename T>
347Box<T>::Box(const T &val) {
348 this->uninit();
349 ::new (this->ptr) T(val);
350}
351
352template <typename T>
353Box<T>::Box(T &&val) {
354 this->uninit();
355 ::new (this->ptr) T(std::move(val));
356}
357
358template <typename T>
359Box<T>::~Box() noexcept {
360 if (this->ptr) {
361 this->drop();
362 }
363}
364
365template <typename T>
366Box<T> &Box<T>::operator=(const Box &other) {
367 if (this != &other) {
368 if (this->ptr) {
369 **this = *other;
370 } else {
371 this->uninit();
372 ::new (this->ptr) T(*other);
373 }
374 }
375 return *this;
376}
377
378template <typename T>
379Box<T> &Box<T>::operator=(Box &&other) noexcept {
380 if (this->ptr) {
381 this->drop();
382 }
383 this->ptr = other.ptr;
384 other.ptr = nullptr;
385 return *this;
386}
387
388template <typename T>
389const T *Box<T>::operator->() const noexcept {
390 return this->ptr;
391}
392
393template <typename T>
394const T &Box<T>::operator*() const noexcept {
395 return *this->ptr;
396}
397
398template <typename T>
399T *Box<T>::operator->() noexcept {
400 return this->ptr;
401}
402
403template <typename T>
404T &Box<T>::operator*() noexcept {
405 return *this->ptr;
406}
407
408template <typename T>
409template <typename... Fields>
410Box<T> Box<T>::in_place(Fields &&... fields) {
411 Box box;
412 box.uninit();
413 ::new (box.ptr) T{std::forward<Fields>(fields)...};
414 return box;
415}
416
417template <typename T>
418Box<T> Box<T>::from_raw(T *raw) noexcept {
419 Box box;
420 box.ptr = raw;
421 return box;
422}
423
424template <typename T>
425T *Box<T>::into_raw() noexcept {
426 T *raw = this->ptr;
427 this->ptr = nullptr;
428 return raw;
429}
430
431template <typename T>
432Box<T>::Box() noexcept {}
433#endif // CXXBRIDGE03_RUST_BOX
434
435#ifndef CXXBRIDGE03_RUST_VEC
436#define CXXBRIDGE03_RUST_VEC
437template <typename T>
438Vec<T>::Vec(Vec &&other) noexcept {
439 this->repr = other.repr;
440 new (&other) Vec();
441}
442
443template <typename T>
444Vec<T>::~Vec() noexcept {
445 this->drop();
446}
447
448template <typename T>
449Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
450 if (this != &other) {
451 this->drop();
452 this->repr = other.repr;
453 new (&other) Vec();
454 }
455 return *this;
456}
457
458template <typename T>
459bool Vec<T>::empty() const noexcept {
460 return size() == 0;
461}
462
463template <typename T>
464const T &Vec<T>::const_iterator::operator*() const noexcept {
465 return *static_cast<const T *>(this->pos);
466}
467
468template <typename T>
469const T *Vec<T>::const_iterator::operator->() const noexcept {
470 return static_cast<const T *>(this->pos);
471}
472
473template <typename T>
474typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
475 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
476 return *this;
477}
478
479template <typename T>
480typename Vec<T>::const_iterator
481Vec<T>::const_iterator::operator++(int) noexcept {
482 auto ret = const_iterator(*this);
483 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
484 return ret;
485}
486
487template <typename T>
488bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
489 noexcept {
490 return this->pos == other.pos;
491}
492
493template <typename T>
494bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
495 noexcept {
496 return this->pos != other.pos;
497}
498
499template <typename T>
500typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
501 const_iterator it;
502 it.pos = this->data();
503 it.stride = this->stride();
504 return it;
505}
506
507template <typename T>
508typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
509 const_iterator it = this->begin();
510 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
511 return it;
512}
513
514// Internal API only intended for the cxxbridge code generator.
515template <typename T>
516Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
517#endif // CXXBRIDGE03_RUST_VEC
518
David Tolnay69601622020-04-29 18:48:36 -0700519} // namespace cxxbridge03
David Tolnay750755e2020-03-01 13:04:08 -0800520} // namespace rust