blob: 03f719fdda8c94c2ac417aae59be1e930034879f [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001#pragma once
David Tolnayf799b372020-11-29 23:57:42 -08002#include <algorithm>
David Tolnay7db73692019-10-20 14:51:12 -04003#include <array>
David Tolnayfa5a4a62020-12-21 14:08:08 -08004#include <cassert>
David Tolnay30430f12020-03-19 20:49:00 -07005#include <cstddef>
David Tolnay7db73692019-10-20 14:51:12 -04006#include <cstdint>
David Tolnayb7a7cb62020-03-17 21:18:40 -07007#include <exception>
David Tolnayf799b372020-11-29 23:57:42 -08008#include <initializer_list>
David Tolnay001102a2020-03-01 20:05:04 -08009#include <iosfwd>
David Tolnayd1df4c72020-11-25 20:38:05 -080010#include <iterator>
David Tolnay0ecd05a2020-07-29 16:32:03 -070011#include <new>
Stephen Crane9e48d5b2020-08-21 12:17:02 -070012#include <stdexcept>
David Tolnay7db73692019-10-20 14:51:12 -040013#include <string>
David Tolnayf6292372020-03-01 21:09:11 -080014#include <type_traits>
David Tolnay4791f1c2020-03-17 21:53:16 -070015#include <utility>
David Tolnay37dd7e12020-04-25 12:51:59 -070016#include <vector>
David Tolnay59b5ba12020-04-10 11:32:19 -070017#if defined(_WIN32)
David Tolnayda38b7c2020-09-16 11:50:04 -040018#include <basetsd.h>
David Tolnay74dd66f2020-12-12 22:03:47 -080019#else
20#include <sys/types.h>
David Tolnay59b5ba12020-04-10 11:32:19 -070021#endif
David Tolnay7db73692019-10-20 14:51:12 -040022
David Tolnay750755e2020-03-01 13:04:08 -080023namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080024inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040025
David Tolnay2a2b9ad2020-05-12 20:07:26 -070026struct unsafe_bitcopy_t;
David Tolnayd1e2efc2020-03-03 22:25:43 -080027
David Tolnay84ddf9e2020-10-31 15:36:48 -070028namespace {
29template <typename T>
30class impl;
31}
32
David Tolnay0f0162f2020-11-16 23:43:37 -080033#ifndef CXXBRIDGE1_RUST_STRING
34#define CXXBRIDGE1_RUST_STRING
David Tolnaye468f052020-11-29 19:39:35 -080035// https://cxx.rs/binding/string.html
David Tolnay56082162020-03-01 12:57:33 -080036class String final {
David Tolnay7db73692019-10-20 14:51:12 -040037public:
David Tolnay56082162020-03-01 12:57:33 -080038 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080039 String(const String &) noexcept;
40 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080041 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080042
43 String(const std::string &);
44 String(const char *);
David Tolnaybe3cbf72020-12-12 22:12:07 -080045 String(const char *, std::size_t);
David Tolnayd9c4ac92020-03-01 20:33:58 -080046
47 String &operator=(const String &) noexcept;
48 String &operator=(String &&) noexcept;
49
David Tolnay404d6892020-03-01 20:19:41 -080050 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040051
52 // Note: no null terminator.
53 const char *data() const noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -080054 std::size_t size() const noexcept;
55 std::size_t length() const noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040056
David Tolnaycca2e612020-12-18 12:48:22 -080057 const char *c_str() noexcept;
58
David Tolnayff7f5fb2020-11-25 20:50:32 -080059 using iterator = char *;
60 iterator begin() noexcept;
61 iterator end() noexcept;
62
63 using const_iterator = const char *;
64 const_iterator begin() const noexcept;
65 const_iterator end() const noexcept;
66 const_iterator cbegin() const noexcept;
67 const_iterator cend() const noexcept;
68
David Tolnayff86dce2020-11-29 19:45:13 -080069 bool operator==(const String &) const noexcept;
70 bool operator!=(const String &) const noexcept;
71 bool operator<(const String &) const noexcept;
72 bool operator<=(const String &) const noexcept;
73 bool operator>(const String &) const noexcept;
74 bool operator>=(const String &) const noexcept;
75
David Tolnayfec17152021-01-02 12:51:29 -080076 void swap(String &) noexcept;
77
David Tolnayd1e2efc2020-03-03 22:25:43 -080078 // Internal API only intended for the cxxbridge code generator.
79 String(unsafe_bitcopy_t, const String &) noexcept;
80
David Tolnay7db73692019-10-20 14:51:12 -040081private:
David Tolnayc9e597e2021-01-02 12:15:06 -080082 friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); }
Cameron Pickettf45f8992021-01-02 18:38:05 +000083
David Tolnay7db73692019-10-20 14:51:12 -040084 // Size and alignment statically verified by rust_string.rs.
David Tolnaybe3cbf72020-12-12 22:12:07 -080085 std::array<std::uintptr_t, 3> repr;
David Tolnay7db73692019-10-20 14:51:12 -040086};
Cameron Pickettf45f8992021-01-02 18:38:05 +000087
David Tolnay0f0162f2020-11-16 23:43:37 -080088#endif // CXXBRIDGE1_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040089
David Tolnay0f0162f2020-11-16 23:43:37 -080090#ifndef CXXBRIDGE1_RUST_STR
David Tolnay1202de52021-01-02 01:26:33 -080091#define CXXBRIDGE1_RUST_STR
David Tolnaye468f052020-11-29 19:39:35 -080092// https://cxx.rs/binding/str.html
David Tolnay09dbe752020-03-01 13:00:40 -080093class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040094public:
David Tolnay09dbe752020-03-01 13:00:40 -080095 Str() noexcept;
David Tolnay828e5132020-11-29 20:40:40 -080096 Str(const String &) noexcept;
David Tolnay851677c2020-03-01 23:49:46 -080097 Str(const std::string &);
98 Str(const char *);
David Tolnaybe3cbf72020-12-12 22:12:07 -080099 Str(const char *, std::size_t);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800100
David Tolnay2d7f1172020-10-31 17:58:31 -0700101 Str &operator=(const Str &) noexcept = default;
David Tolnayd9c4ac92020-03-01 20:33:58 -0800102
David Tolnay404d6892020-03-01 20:19:41 -0800103 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -0400104
105 // Note: no null terminator.
106 const char *data() const noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800107 std::size_t size() const noexcept;
108 std::size_t length() const noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400109
David Tolnayde9a5b12020-10-31 12:15:43 -0700110 // Important in order for System V ABI to pass in registers.
111 Str(const Str &) noexcept = default;
112 ~Str() noexcept = default;
113
David Tolnayff7f5fb2020-11-25 20:50:32 -0800114 using iterator = const char *;
115 using const_iterator = const char *;
116 const_iterator begin() const noexcept;
117 const_iterator end() const noexcept;
118 const_iterator cbegin() const noexcept;
119 const_iterator cend() const noexcept;
120
David Tolnayff86dce2020-11-29 19:45:13 -0800121 bool operator==(const Str &) const noexcept;
122 bool operator!=(const Str &) const noexcept;
123 bool operator<(const Str &) const noexcept;
124 bool operator<=(const Str &) const noexcept;
125 bool operator>(const Str &) const noexcept;
126 bool operator>=(const Str &) const noexcept;
127
David Tolnay0413ee22021-01-02 13:55:16 -0800128 void swap(Str &) noexcept;
129
David Tolnay5df1f062020-10-31 12:31:10 -0700130private:
David Tolnay1202de52021-01-02 01:26:33 -0800131 std::array<std::uintptr_t, 2> repr;
David Tolnay7db73692019-10-20 14:51:12 -0400132};
David Tolnay0f0162f2020-11-16 23:43:37 -0800133#endif // CXXBRIDGE1_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -0400134
David Tolnay0f0162f2020-11-16 23:43:37 -0800135#ifndef CXXBRIDGE1_RUST_SLICE
David Tolnayc5629f02020-11-23 18:32:46 -0800136namespace detail {
David Tolnayee9b9ee2020-11-25 08:28:50 -0800137template <bool>
David Tolnayc5629f02020-11-23 18:32:46 -0800138struct copy_assignable_if {};
David Tolnayce298232020-11-11 10:08:54 -0800139
David Tolnayc5629f02020-11-23 18:32:46 -0800140template <>
141struct copy_assignable_if<false> {
142 copy_assignable_if() noexcept = default;
143 copy_assignable_if(const copy_assignable_if &) noexcept = default;
144 copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
145 copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
146};
147} // namespace detail
148
David Tolnaye468f052020-11-29 19:39:35 -0800149// https://cxx.rs/binding/slice.html
David Tolnayc5629f02020-11-23 18:32:46 -0800150template <typename T>
151class Slice final
152 : private detail::copy_assignable_if<std::is_const<T>::value> {
David Tolnayefe81052020-04-14 16:28:24 -0700153public:
David Tolnayf62458f2020-12-27 19:38:43 -0800154 using value_type = T;
155
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700156 Slice() noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800157 Slice(T *, std::size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700158
David Tolnay2d7f1172020-10-31 17:58:31 -0700159 Slice &operator=(const Slice<T> &) noexcept = default;
David Tolnayc5629f02020-11-23 18:32:46 -0800160 Slice &operator=(Slice<T> &&) noexcept = default;
David Tolnayefe81052020-04-14 16:28:24 -0700161
David Tolnayce298232020-11-11 10:08:54 -0800162 T *data() const noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800163 std::size_t size() const noexcept;
164 std::size_t length() const noexcept;
David Tolnay78dd5352020-12-26 23:44:20 -0800165 bool empty() const noexcept;
166
167 T &operator[](std::size_t n) const noexcept;
168 T &at(std::size_t n) const;
169 T &front() const noexcept;
170 T &back() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700171
David Tolnayde9a5b12020-10-31 12:15:43 -0700172 // Important in order for System V ABI to pass in registers.
173 Slice(const Slice<T> &) noexcept = default;
174 ~Slice() noexcept = default;
175
David Tolnayac6cb542020-11-25 20:18:55 -0800176 class iterator;
177 iterator begin() const noexcept;
178 iterator end() const noexcept;
179
David Tolnay0413ee22021-01-02 13:55:16 -0800180 void swap(Slice &) noexcept;
181
David Tolnayefe81052020-04-14 16:28:24 -0700182private:
David Tolnay36aa9e02020-10-31 23:08:21 -0700183 // Not necessarily ABI compatible with &[T]. Codegen will translate to
David Tolnay5515a9e2020-11-25 19:07:54 -0800184 // cxx::rust_slice::RustSlice which matches this layout.
David Tolnay5ce110e2020-12-27 02:45:53 -0800185 void *ptr;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800186 std::size_t len;
David Tolnayefe81052020-04-14 16:28:24 -0700187};
David Tolnayac6cb542020-11-25 20:18:55 -0800188
189template <typename T>
190class Slice<T>::iterator final {
191public:
David Tolnayc30e4472020-12-27 00:25:42 -0800192 using iterator_category = std::random_access_iterator_tag;
David Tolnayac6cb542020-11-25 20:18:55 -0800193 using value_type = T;
David Tolnayc30e4472020-12-27 00:25:42 -0800194 using difference_type = std::ptrdiff_t;
David Tolnayac6cb542020-11-25 20:18:55 -0800195 using pointer = typename std::add_pointer<T>::type;
196 using reference = typename std::add_lvalue_reference<T>::type;
David Tolnayac6cb542020-11-25 20:18:55 -0800197
David Tolnaydb388c92020-12-27 00:28:26 -0800198 reference operator*() const noexcept;
199 pointer operator->() const noexcept;
David Tolnayc30e4472020-12-27 00:25:42 -0800200 reference operator[](difference_type) const noexcept;
201
David Tolnayac6cb542020-11-25 20:18:55 -0800202 iterator &operator++() noexcept;
203 iterator operator++(int) noexcept;
David Tolnayc30e4472020-12-27 00:25:42 -0800204 iterator &operator--() noexcept;
205 iterator operator--(int) noexcept;
206
207 iterator &operator+=(difference_type) noexcept;
208 iterator &operator-=(difference_type) noexcept;
209 iterator operator+(difference_type) const noexcept;
210 iterator operator-(difference_type) const noexcept;
211 difference_type operator-(const iterator &) const noexcept;
212
David Tolnayac6cb542020-11-25 20:18:55 -0800213 bool operator==(const iterator &) const noexcept;
214 bool operator!=(const iterator &) const noexcept;
David Tolnayc30e4472020-12-27 00:25:42 -0800215 bool operator<(const iterator &) const noexcept;
216 bool operator<=(const iterator &) const noexcept;
217 bool operator>(const iterator &) const noexcept;
218 bool operator>=(const iterator &) const noexcept;
David Tolnayac6cb542020-11-25 20:18:55 -0800219
220private:
221 friend class Slice;
David Tolnaya1ddbf82020-12-27 00:56:35 -0800222 void *pos;
223 std::size_t stride;
David Tolnayac6cb542020-11-25 20:18:55 -0800224};
David Tolnay0f0162f2020-11-16 23:43:37 -0800225#endif // CXXBRIDGE1_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700226
David Tolnay0f0162f2020-11-16 23:43:37 -0800227#ifndef CXXBRIDGE1_RUST_BOX
David Tolnaye468f052020-11-29 19:39:35 -0800228// https://cxx.rs/binding/box.html
David Tolnayf262d382020-04-11 22:12:40 -0700229template <typename T>
230class Box final {
David Tolnay7db73692019-10-20 14:51:12 -0400231public:
David Tolnaye47a4d92020-12-27 19:35:21 -0800232 using element_type = T;
David Tolnay9706a512020-04-24 17:09:01 -0700233 using const_pointer =
234 typename std::add_pointer<typename std::add_const<T>::type>::type;
235 using pointer = typename std::add_pointer<T>::type;
David Tolnayf6292372020-03-01 21:09:11 -0800236
David Tolnayc4b34222020-12-12 13:06:26 -0800237 Box() = delete;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700238 Box(Box &&) noexcept;
239 ~Box() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400240
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700241 explicit Box(const T &);
242 explicit Box(T &&);
243
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700244 Box &operator=(Box &&) noexcept;
245
246 const T *operator->() const noexcept;
247 const T &operator*() const noexcept;
248 T *operator->() noexcept;
249 T &operator*() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400250
David Tolnayf262d382020-04-11 22:12:40 -0700251 template <typename... Fields>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700252 static Box in_place(Fields &&...);
David Tolnay7ce59fc2020-04-11 11:46:33 -0700253
David Tolnayfec17152021-01-02 12:51:29 -0800254 void swap(Box &) noexcept;
255
David Tolnay7db73692019-10-20 14:51:12 -0400256 // Important: requires that `raw` came from an into_raw call. Do not pass a
257 // pointer from `new` or any other source.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700258 static Box from_raw(T *) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400259
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700260 T *into_raw() noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400261
David Tolnay78a5f8d2020-12-28 11:40:38 -0800262 /* Deprecated */ using value_type = element_type;
David Tolnaye47a4d92020-12-27 19:35:21 -0800263
David Tolnay7db73692019-10-20 14:51:12 -0400264private:
David Tolnayc4b34222020-12-12 13:06:26 -0800265 class uninit;
David Tolnaye5703162020-12-12 16:26:35 -0800266 class allocation;
David Tolnayc4b34222020-12-12 13:06:26 -0800267 Box(uninit) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -0400268 void drop() noexcept;
Cameron Pickettf45f8992021-01-02 18:38:05 +0000269
David Tolnayc9e597e2021-01-02 12:15:06 -0800270 friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); }
Cameron Pickettf45f8992021-01-02 18:38:05 +0000271
David Tolnay33169bd2020-03-06 13:02:08 -0800272 T *ptr;
David Tolnay7db73692019-10-20 14:51:12 -0400273};
David Tolnay0f0162f2020-11-16 23:43:37 -0800274#endif // CXXBRIDGE1_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400275
David Tolnay0f0162f2020-11-16 23:43:37 -0800276#ifndef CXXBRIDGE1_RUST_VEC
David Tolnaye468f052020-11-29 19:39:35 -0800277// https://cxx.rs/binding/vec.html
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700278template <typename T>
279class Vec final {
280public:
David Tolnayc87c2152020-04-24 17:07:41 -0700281 using value_type = T;
282
David Tolnayf97c2d52020-04-25 16:37:48 -0700283 Vec() noexcept;
David Tolnayf799b372020-11-29 23:57:42 -0800284 Vec(std::initializer_list<T>);
David Tolnay9007e462020-12-11 13:59:08 -0800285 Vec(const Vec &);
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700286 Vec(Vec &&) noexcept;
287 ~Vec() noexcept;
David Tolnaycb800572020-04-24 20:30:43 -0700288
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700289 Vec &operator=(Vec &&) noexcept;
David Tolnaydd42c722020-12-11 14:05:26 -0800290 Vec &operator=(const Vec &);
David Tolnayf97c2d52020-04-25 16:37:48 -0700291
David Tolnaybe3cbf72020-12-12 22:12:07 -0800292 std::size_t size() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700293 bool empty() const noexcept;
David Tolnay219c0792020-04-24 20:31:37 -0700294 const T *data() const noexcept;
David Tolnayfb6b73c2020-11-10 14:32:16 -0800295 T *data() noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800296 std::size_t capacity() const noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700297
David Tolnaybe3cbf72020-12-12 22:12:07 -0800298 const T &operator[](std::size_t n) const noexcept;
299 const T &at(std::size_t n) const;
David Tolnayd4fff5d2020-12-21 14:04:09 -0800300 const T &front() const noexcept;
301 const T &back() const noexcept;
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700302
David Tolnaybe3cbf72020-12-12 22:12:07 -0800303 T &operator[](std::size_t n) noexcept;
304 T &at(std::size_t n);
David Tolnayd4fff5d2020-12-21 14:04:09 -0800305 T &front() noexcept;
306 T &back() noexcept;
David Tolnay908d5e52020-11-30 00:30:59 -0800307
David Tolnaybe3cbf72020-12-12 22:12:07 -0800308 void reserve(std::size_t new_cap);
David Tolnayfb6b73c2020-11-10 14:32:16 -0800309 void push_back(const T &value);
310 void push_back(T &&value);
David Tolnay4e8c49a2020-11-11 10:00:18 -0800311 template <typename... Args>
David Tolnayfb6b73c2020-11-10 14:32:16 -0800312 void emplace_back(Args &&... args);
313
David Tolnay725bf502020-12-27 02:47:40 -0800314 using iterator = typename Slice<T>::iterator;
David Tolnay960b5112020-11-25 13:18:28 -0800315 iterator begin() noexcept;
316 iterator end() noexcept;
317
David Tolnay725bf502020-12-27 02:47:40 -0800318 using const_iterator = typename Slice<const T>::iterator;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700319 const_iterator begin() const noexcept;
320 const_iterator end() const noexcept;
David Tolnay960b5112020-11-25 13:18:28 -0800321 const_iterator cbegin() const noexcept;
322 const_iterator cend() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700323
David Tolnayfec17152021-01-02 12:51:29 -0800324 void swap(Vec &) noexcept;
325
David Tolnay313b10e2020-04-25 16:30:51 -0700326 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700327 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700328
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700329private:
David Tolnaybe3cbf72020-12-12 22:12:07 -0800330 void reserve_total(std::size_t cap) noexcept;
331 void set_len(std::size_t len) noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700332 void drop() noexcept;
333
David Tolnaycf7bb9b2021-01-02 13:03:28 -0800334 friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); }
Cameron Pickettf45f8992021-01-02 18:38:05 +0000335
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700336 // Size and alignment statically verified by rust_vec.rs.
David Tolnaybe3cbf72020-12-12 22:12:07 -0800337 std::array<std::uintptr_t, 3> repr;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700338};
David Tolnay0f0162f2020-11-16 23:43:37 -0800339#endif // CXXBRIDGE1_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700340
David Tolnay0f0162f2020-11-16 23:43:37 -0800341#ifndef CXXBRIDGE1_RUST_FN
David Tolnaye468f052020-11-29 19:39:35 -0800342// https://cxx.rs/binding/fn.html
David Tolnayf031c322020-11-29 19:41:33 -0800343template <typename Signature>
David Tolnayf262d382020-04-11 22:12:40 -0700344class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700345
David Tolnayf031c322020-11-29 19:41:33 -0800346template <typename Ret, typename... Args>
347class Fn<Ret(Args...)> final {
David Tolnay75dca2e2020-03-25 20:17:52 -0700348public:
David Tolnayf031c322020-11-29 19:41:33 -0800349 Ret operator()(Args... args) const noexcept;
David Tolnay533d4582020-04-08 20:29:14 -0700350 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700351
352private:
David Tolnayf031c322020-11-29 19:41:33 -0800353 Ret (*trampoline)(Args..., void *fn) noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700354 void *fn;
355};
David Tolnay0f0162f2020-11-16 23:43:37 -0800356#endif // CXXBRIDGE1_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700357
David Tolnay0f0162f2020-11-16 23:43:37 -0800358#ifndef CXXBRIDGE1_RUST_ERROR
359#define CXXBRIDGE1_RUST_ERROR
David Tolnaye468f052020-11-29 19:39:35 -0800360// https://cxx.rs/binding/result.html
David Tolnaye4fa8732020-09-08 15:04:56 -0700361class Error final : public std::exception {
David Tolnay1e548172020-03-16 13:37:09 -0700362public:
363 Error(const Error &);
364 Error(Error &&) noexcept;
David Tolnay2714d2c2020-11-23 18:17:43 -0800365 ~Error() noexcept override;
David Tolnay7c6ac712020-10-31 17:22:28 -0700366
367 Error &operator=(const Error &);
David Tolnay15491062020-10-31 17:25:13 -0700368 Error &operator=(Error &&) noexcept;
David Tolnay7c6ac712020-10-31 17:22:28 -0700369
David Tolnay1e548172020-03-16 13:37:09 -0700370 const char *what() const noexcept override;
371
372private:
David Tolnaya0c9bc72020-10-31 14:37:14 -0700373 Error() noexcept = default;
David Tolnay84ddf9e2020-10-31 15:36:48 -0700374 friend impl<Error>;
David Tolnaya0c9bc72020-10-31 14:37:14 -0700375 const char *msg;
David Tolnaybe3cbf72020-12-12 22:12:07 -0800376 std::size_t len;
David Tolnay1e548172020-03-16 13:37:09 -0700377};
David Tolnay0f0162f2020-11-16 23:43:37 -0800378#endif // CXXBRIDGE1_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700379
David Tolnay0f0162f2020-11-16 23:43:37 -0800380#ifndef CXXBRIDGE1_RUST_ISIZE
381#define CXXBRIDGE1_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700382#if defined(_WIN32)
383using isize = SSIZE_T;
384#else
385using isize = ssize_t;
386#endif
David Tolnay0f0162f2020-11-16 23:43:37 -0800387#endif // CXXBRIDGE1_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700388
David Tolnay851677c2020-03-01 23:49:46 -0800389std::ostream &operator<<(std::ostream &, const String &);
390std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400391
David Tolnay365fc7c2020-11-25 16:08:13 -0800392#ifndef CXXBRIDGE1_RUST_OPAQUE
393#define CXXBRIDGE1_RUST_OPAQUE
394// Base class of generated opaque Rust types.
395class Opaque {
David Tolnaya857c322020-11-25 16:27:19 -0800396public:
David Tolnay365fc7c2020-11-25 16:08:13 -0800397 Opaque() = delete;
398 Opaque(const Opaque &) = delete;
399 ~Opaque() = delete;
400};
401#endif // CXXBRIDGE1_RUST_OPAQUE
402
David Tolnayee6ecfc2020-12-26 21:54:37 -0800403template <typename T>
404std::size_t size_of();
405template <typename T>
406std::size_t align_of();
407
David Tolnay174bd952020-11-02 09:23:12 -0800408// IsRelocatable<T> is used in assertions that a C++ type passed by value
409// between Rust and C++ is soundly relocatable by Rust.
410//
411// There may be legitimate reasons to opt out of the check for support of types
412// that the programmer knows are soundly Rust-movable despite not being
413// recognized as such by the C++ type system due to a move constructor or
414// destructor. To opt out of the relocatability check, do either of the
415// following things in any header used by `include!` in the bridge.
416//
417// --- if you define the type:
418// struct MyType {
419// ...
420// + using IsRelocatable = std::true_type;
421// };
422//
423// --- otherwise:
424// + template <>
425// + struct rust::IsRelocatable<MyType> : std::true_type {};
426template <typename T>
427struct IsRelocatable;
428
David Tolnaybe3cbf72020-12-12 22:12:07 -0800429using u8 = std::uint8_t;
430using u16 = std::uint16_t;
431using u32 = std::uint32_t;
432using u64 = std::uint64_t;
433using usize = std::size_t; // see static asserts in cxx.cc
434using i8 = std::int8_t;
435using i16 = std::int16_t;
436using i32 = std::int32_t;
437using i64 = std::int64_t;
David Tolnay1e784a32020-12-12 21:34:47 -0800438using f32 = float;
439using f64 = double;
440
David Tolnay3b0c9882020-03-01 14:08:57 -0800441// Snake case aliases for use in code that uses this style for type names.
442using string = String;
443using str = Str;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800444template <typename T>
David Tolnay38c87642020-09-06 22:18:08 -0700445using slice = Slice<T>;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800446template <typename T>
David Tolnayf262d382020-04-11 22:12:40 -0700447using box = Box<T>;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800448template <typename T>
David Tolnay38c87642020-09-06 22:18:08 -0700449using vec = Vec<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700450using error = Error;
David Tolnayf262d382020-04-11 22:12:40 -0700451template <typename Signature>
David Tolnayf031c322020-11-29 19:41:33 -0800452using fn = Fn<Signature>;
David Tolnay174bd952020-11-02 09:23:12 -0800453template <typename T>
454using is_relocatable = IsRelocatable<T>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800455
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700456
457
458////////////////////////////////////////////////////////////////////////////////
459/// end public API, begin implementation details
460
David Tolnay0f0162f2020-11-16 23:43:37 -0800461#ifndef CXXBRIDGE1_PANIC
462#define CXXBRIDGE1_PANIC
David Tolnay521d99d2020-08-26 20:45:40 -0700463template <typename Exception>
464void panic [[noreturn]] (const char *msg);
David Tolnay0f0162f2020-11-16 23:43:37 -0800465#endif // CXXBRIDGE1_PANIC
David Tolnay521d99d2020-08-26 20:45:40 -0700466
David Tolnay0f0162f2020-11-16 23:43:37 -0800467#ifndef CXXBRIDGE1_RUST_FN
468#define CXXBRIDGE1_RUST_FN
David Tolnayf031c322020-11-29 19:41:33 -0800469template <typename Ret, typename... Args>
470Ret Fn<Ret(Args...)>::operator()(Args... args) const noexcept {
David Tolnay75dca2e2020-03-25 20:17:52 -0700471 return (*this->trampoline)(std::move(args)..., this->fn);
472}
473
David Tolnayf031c322020-11-29 19:41:33 -0800474template <typename Ret, typename... Args>
475Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700476 return *this;
477}
David Tolnay0f0162f2020-11-16 23:43:37 -0800478#endif // CXXBRIDGE1_RUST_FN
David Tolnaya23129c2020-04-08 20:08:21 -0700479
David Tolnay0f0162f2020-11-16 23:43:37 -0800480#ifndef CXXBRIDGE1_RUST_BITCOPY
481#define CXXBRIDGE1_RUST_BITCOPY
David Tolnay48521222020-10-31 14:59:42 -0700482struct unsafe_bitcopy_t final {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700483 explicit unsafe_bitcopy_t() = default;
484};
485
486constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnay0f0162f2020-11-16 23:43:37 -0800487#endif // CXXBRIDGE1_RUST_BITCOPY
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700488
David Tolnay0f0162f2020-11-16 23:43:37 -0800489#ifndef CXXBRIDGE1_RUST_SLICE
490#define CXXBRIDGE1_RUST_SLICE
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700491template <typename T>
David Tolnayeee622c2020-12-27 01:26:17 -0800492Slice<T>::Slice() noexcept
David Tolnay5ce110e2020-12-27 02:45:53 -0800493 : ptr(reinterpret_cast<void *>(align_of<T>())), len(0) {}
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700494
495template <typename T>
David Tolnay5ce110e2020-12-27 02:45:53 -0800496Slice<T>::Slice(T *s, std::size_t count) noexcept
497 : ptr(const_cast<typename std::remove_const<T>::type *>(s)), len(count) {}
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700498
499template <typename T>
David Tolnayce298232020-11-11 10:08:54 -0800500T *Slice<T>::data() const noexcept {
David Tolnay5ce110e2020-12-27 02:45:53 -0800501 return reinterpret_cast<T *>(this->ptr);
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700502}
503
504template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800505std::size_t Slice<T>::size() const noexcept {
David Tolnay36aa9e02020-10-31 23:08:21 -0700506 return this->len;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700507}
508
509template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800510std::size_t Slice<T>::length() const noexcept {
David Tolnay36aa9e02020-10-31 23:08:21 -0700511 return this->len;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700512}
David Tolnayac6cb542020-11-25 20:18:55 -0800513
514template <typename T>
David Tolnay78dd5352020-12-26 23:44:20 -0800515bool Slice<T>::empty() const noexcept {
516 return this->len == 0;
517}
518
519template <typename T>
520T &Slice<T>::operator[](std::size_t n) const noexcept {
521 assert(n < this->size());
David Tolnay5ce110e2020-12-27 02:45:53 -0800522 auto pos = static_cast<char *>(this->ptr) + size_of<T>() * n;
523 return *reinterpret_cast<T *>(pos);
David Tolnay78dd5352020-12-26 23:44:20 -0800524}
525
526template <typename T>
527T &Slice<T>::at(std::size_t n) const {
528 if (n >= this->size()) {
529 panic<std::out_of_range>("rust::Slice index out of range");
530 }
531 return (*this)[n];
532}
533
534template <typename T>
535T &Slice<T>::front() const noexcept {
536 assert(!this->empty());
David Tolnay5ce110e2020-12-27 02:45:53 -0800537 return (*this)[0];
David Tolnay78dd5352020-12-26 23:44:20 -0800538}
539
540template <typename T>
541T &Slice<T>::back() const noexcept {
542 assert(!this->empty());
David Tolnay5ce110e2020-12-27 02:45:53 -0800543 return (*this)[this->len - 1];
David Tolnay78dd5352020-12-26 23:44:20 -0800544}
545
546template <typename T>
David Tolnaydb388c92020-12-27 00:28:26 -0800547typename Slice<T>::iterator::reference
548Slice<T>::iterator::operator*() const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800549 return *static_cast<T *>(this->pos);
David Tolnayac6cb542020-11-25 20:18:55 -0800550}
551
552template <typename T>
David Tolnaydb388c92020-12-27 00:28:26 -0800553typename Slice<T>::iterator::pointer
554Slice<T>::iterator::operator->() const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800555 return static_cast<T *>(this->pos);
David Tolnayac6cb542020-11-25 20:18:55 -0800556}
557
558template <typename T>
David Tolnayc30e4472020-12-27 00:25:42 -0800559typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
560 typename Slice<T>::iterator::difference_type n) const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800561 auto pos = static_cast<char *>(this->pos) + this->stride * n;
David Tolnay7f59a692021-01-02 00:07:24 -0800562 return *reinterpret_cast<T *>(pos);
David Tolnayc30e4472020-12-27 00:25:42 -0800563}
564
565template <typename T>
David Tolnayac6cb542020-11-25 20:18:55 -0800566typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800567 this->pos = static_cast<char *>(this->pos) + this->stride;
David Tolnayac6cb542020-11-25 20:18:55 -0800568 return *this;
569}
570
571template <typename T>
572typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
573 auto ret = iterator(*this);
David Tolnaya1ddbf82020-12-27 00:56:35 -0800574 this->pos = static_cast<char *>(this->pos) + this->stride;
David Tolnayac6cb542020-11-25 20:18:55 -0800575 return ret;
576}
577
578template <typename T>
David Tolnayc30e4472020-12-27 00:25:42 -0800579typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800580 this->pos = static_cast<char *>(this->pos) - this->stride;
David Tolnayc30e4472020-12-27 00:25:42 -0800581 return *this;
582}
583
584template <typename T>
585typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {
586 auto ret = iterator(*this);
David Tolnaya1ddbf82020-12-27 00:56:35 -0800587 this->pos = static_cast<char *>(this->pos) - this->stride;
David Tolnayc30e4472020-12-27 00:25:42 -0800588 return ret;
589}
590
591template <typename T>
592typename Slice<T>::iterator &Slice<T>::iterator::operator+=(
593 typename Slice<T>::iterator::difference_type n) noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800594 this->pos = static_cast<char *>(this->pos) + this->stride * n;
David Tolnayc30e4472020-12-27 00:25:42 -0800595 return *this;
596}
597
598template <typename T>
599typename Slice<T>::iterator &Slice<T>::iterator::operator-=(
600 typename Slice<T>::iterator::difference_type n) noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800601 this->pos = static_cast<char *>(this->pos) - this->stride * n;
David Tolnayc30e4472020-12-27 00:25:42 -0800602 return *this;
603}
604
605template <typename T>
606typename Slice<T>::iterator Slice<T>::iterator::operator+(
607 typename Slice<T>::iterator::difference_type n) const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800608 auto ret = iterator(*this);
609 ret.pos = static_cast<char *>(this->pos) + this->stride * n;
610 return ret;
David Tolnayc30e4472020-12-27 00:25:42 -0800611}
612
613template <typename T>
614typename Slice<T>::iterator Slice<T>::iterator::operator-(
615 typename Slice<T>::iterator::difference_type n) const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800616 auto ret = iterator(*this);
617 ret.pos = static_cast<char *>(this->pos) - this->stride * n;
618 return ret;
David Tolnayc30e4472020-12-27 00:25:42 -0800619}
620
621template <typename T>
622typename Slice<T>::iterator::difference_type
623Slice<T>::iterator::operator-(const iterator &other) const noexcept {
David Tolnaya1ddbf82020-12-27 00:56:35 -0800624 auto diff = std::distance(static_cast<char *>(other.pos),
625 static_cast<char *>(this->pos));
626 return diff / this->stride;
David Tolnayc30e4472020-12-27 00:25:42 -0800627}
628
629template <typename T>
David Tolnayac6cb542020-11-25 20:18:55 -0800630bool Slice<T>::iterator::operator==(const iterator &other) const noexcept {
631 return this->pos == other.pos;
632}
633
634template <typename T>
635bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {
636 return this->pos != other.pos;
637}
638
639template <typename T>
David Tolnayc30e4472020-12-27 00:25:42 -0800640bool Slice<T>::iterator::operator<(const iterator &other) const noexcept {
641 return this->pos < other.pos;
642}
643
644template <typename T>
645bool Slice<T>::iterator::operator<=(const iterator &other) const noexcept {
646 return this->pos <= other.pos;
647}
648
649template <typename T>
650bool Slice<T>::iterator::operator>(const iterator &other) const noexcept {
651 return this->pos > other.pos;
652}
653
654template <typename T>
655bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
656 return this->pos >= other.pos;
657}
658
659template <typename T>
David Tolnayac6cb542020-11-25 20:18:55 -0800660typename Slice<T>::iterator Slice<T>::begin() const noexcept {
661 iterator it;
David Tolnay5ce110e2020-12-27 02:45:53 -0800662 it.pos = this->ptr;
David Tolnay6f92baa2020-12-27 01:09:26 -0800663 it.stride = size_of<T>();
David Tolnayac6cb542020-11-25 20:18:55 -0800664 return it;
665}
666
667template <typename T>
668typename Slice<T>::iterator Slice<T>::end() const noexcept {
669 iterator it = this->begin();
David Tolnaya1ddbf82020-12-27 00:56:35 -0800670 it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
David Tolnayac6cb542020-11-25 20:18:55 -0800671 return it;
672}
David Tolnay0413ee22021-01-02 13:55:16 -0800673
674template <typename T>
675void Slice<T>::swap(Slice &rhs) noexcept {
676 std::swap(*this, rhs);
677}
David Tolnay0f0162f2020-11-16 23:43:37 -0800678#endif // CXXBRIDGE1_RUST_SLICE
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700679
David Tolnay0f0162f2020-11-16 23:43:37 -0800680#ifndef CXXBRIDGE1_RUST_BOX
681#define CXXBRIDGE1_RUST_BOX
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700682template <typename T>
David Tolnayc4b34222020-12-12 13:06:26 -0800683class Box<T>::uninit {};
684
685template <typename T>
David Tolnaye5703162020-12-12 16:26:35 -0800686class Box<T>::allocation {
David Tolnayf448e202020-12-12 16:42:45 -0800687 static T *alloc() noexcept;
688 static void dealloc(T *) noexcept;
David Tolnay2e637d92020-12-12 21:08:01 -0800689
David Tolnaye5703162020-12-12 16:26:35 -0800690public:
David Tolnaye7d662d2020-12-12 16:38:22 -0800691 allocation() noexcept : ptr(alloc()) {}
692 ~allocation() noexcept {
693 if (this->ptr) {
694 dealloc(this->ptr);
695 }
696 }
David Tolnaye5703162020-12-12 16:26:35 -0800697 T *ptr;
698};
699
700template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700701Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
702 other.ptr = nullptr;
703}
704
705template <typename T>
David Tolnaye7d662d2020-12-12 16:38:22 -0800706Box<T>::Box(const T &val) {
707 allocation alloc;
708 ::new (alloc.ptr) T(val);
709 this->ptr = alloc.ptr;
710 alloc.ptr = nullptr;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700711}
712
713template <typename T>
David Tolnaye7d662d2020-12-12 16:38:22 -0800714Box<T>::Box(T &&val) {
715 allocation alloc;
716 ::new (alloc.ptr) T(std::move(val));
717 this->ptr = alloc.ptr;
718 alloc.ptr = nullptr;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700719}
720
721template <typename T>
722Box<T>::~Box() noexcept {
723 if (this->ptr) {
724 this->drop();
725 }
726}
727
728template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700729Box<T> &Box<T>::operator=(Box &&other) noexcept {
730 if (this->ptr) {
731 this->drop();
732 }
733 this->ptr = other.ptr;
734 other.ptr = nullptr;
735 return *this;
736}
737
738template <typename T>
739const T *Box<T>::operator->() const noexcept {
740 return this->ptr;
741}
742
743template <typename T>
744const T &Box<T>::operator*() const noexcept {
745 return *this->ptr;
746}
747
748template <typename T>
749T *Box<T>::operator->() noexcept {
750 return this->ptr;
751}
752
753template <typename T>
754T &Box<T>::operator*() noexcept {
755 return *this->ptr;
756}
757
758template <typename T>
759template <typename... Fields>
760Box<T> Box<T>::in_place(Fields &&... fields) {
David Tolnaye7d662d2020-12-12 16:38:22 -0800761 allocation alloc;
762 auto ptr = alloc.ptr;
763 ::new (ptr) T{std::forward<Fields>(fields)...};
764 alloc.ptr = nullptr;
765 return from_raw(ptr);
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700766}
767
768template <typename T>
David Tolnaycf7bb9b2021-01-02 13:03:28 -0800769void Box<T>::swap(Box &rhs) noexcept {
David Tolnayfec17152021-01-02 12:51:29 -0800770 using std::swap;
771 swap(this->ptr, rhs.ptr);
772}
773
774template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700775Box<T> Box<T>::from_raw(T *raw) noexcept {
David Tolnayc4b34222020-12-12 13:06:26 -0800776 Box box = uninit{};
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700777 box.ptr = raw;
778 return box;
779}
780
781template <typename T>
782T *Box<T>::into_raw() noexcept {
783 T *raw = this->ptr;
784 this->ptr = nullptr;
785 return raw;
786}
787
788template <typename T>
David Tolnayc4b34222020-12-12 13:06:26 -0800789Box<T>::Box(uninit) noexcept {}
David Tolnay0f0162f2020-11-16 23:43:37 -0800790#endif // CXXBRIDGE1_RUST_BOX
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700791
David Tolnay0f0162f2020-11-16 23:43:37 -0800792#ifndef CXXBRIDGE1_RUST_VEC
793#define CXXBRIDGE1_RUST_VEC
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700794template <typename T>
David Tolnayf799b372020-11-29 23:57:42 -0800795Vec<T>::Vec(std::initializer_list<T> init) : Vec{} {
796 this->reserve_total(init.size());
797 std::move(init.begin(), init.end(), std::back_inserter(*this));
798}
799
800template <typename T>
David Tolnay9007e462020-12-11 13:59:08 -0800801Vec<T>::Vec(const Vec &other) : Vec() {
802 this->reserve_total(other.size());
803 std::copy(other.begin(), other.end(), std::back_inserter(*this));
804}
805
806template <typename T>
David Tolnay15671862020-11-23 18:13:56 -0800807Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700808 new (&other) Vec();
809}
810
811template <typename T>
812Vec<T>::~Vec() noexcept {
813 this->drop();
814}
815
816template <typename T>
817Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
818 if (this != &other) {
819 this->drop();
820 this->repr = other.repr;
821 new (&other) Vec();
822 }
823 return *this;
824}
825
826template <typename T>
David Tolnaydd42c722020-12-11 14:05:26 -0800827Vec<T> &Vec<T>::operator=(const Vec &other) {
828 if (this != &other) {
829 this->drop();
830 new (this) Vec(other);
831 }
832 return *this;
833}
834
835template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700836bool Vec<T>::empty() const noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800837 return this->size() == 0;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700838}
839
840template <typename T>
David Tolnayfb6b73c2020-11-10 14:32:16 -0800841T *Vec<T>::data() noexcept {
842 return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());
843}
844
845template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800846const T &Vec<T>::operator[](std::size_t n) const noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800847 assert(n < this->size());
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700848 auto data = reinterpret_cast<const char *>(this->data());
David Tolnaye1df7dd2020-12-27 02:51:51 -0800849 return *reinterpret_cast<const T *>(data + n * size_of<T>());
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700850}
851
852template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800853const T &Vec<T>::at(std::size_t n) const {
David Tolnay8e1e6ac2020-08-26 20:51:43 -0700854 if (n >= this->size()) {
855 panic<std::out_of_range>("rust::Vec index out of range");
856 }
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700857 return (*this)[n];
858}
859
860template <typename T>
David Tolnayd4fff5d2020-12-21 14:04:09 -0800861const T &Vec<T>::front() const noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800862 assert(!this->empty());
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700863 return (*this)[0];
864}
865
866template <typename T>
David Tolnayd4fff5d2020-12-21 14:04:09 -0800867const T &Vec<T>::back() const noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800868 assert(!this->empty());
David Tolnayb10c4bc2020-08-26 21:55:29 -0700869 return (*this)[this->size() - 1];
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700870}
871
872template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800873T &Vec<T>::operator[](std::size_t n) noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800874 assert(n < this->size());
David Tolnay908d5e52020-11-30 00:30:59 -0800875 auto data = reinterpret_cast<char *>(this->data());
David Tolnaye1df7dd2020-12-27 02:51:51 -0800876 return *reinterpret_cast<T *>(data + n * size_of<T>());
David Tolnay908d5e52020-11-30 00:30:59 -0800877}
878
879template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800880T &Vec<T>::at(std::size_t n) {
David Tolnay908d5e52020-11-30 00:30:59 -0800881 if (n >= this->size()) {
882 panic<std::out_of_range>("rust::Vec index out of range");
883 }
884 return (*this)[n];
885}
886
887template <typename T>
David Tolnayd4fff5d2020-12-21 14:04:09 -0800888T &Vec<T>::front() noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800889 assert(!this->empty());
David Tolnay908d5e52020-11-30 00:30:59 -0800890 return (*this)[0];
891}
892
893template <typename T>
David Tolnayd4fff5d2020-12-21 14:04:09 -0800894T &Vec<T>::back() noexcept {
David Tolnayfa5a4a62020-12-21 14:08:08 -0800895 assert(!this->empty());
David Tolnay908d5e52020-11-30 00:30:59 -0800896 return (*this)[this->size() - 1];
897}
898
899template <typename T>
David Tolnaybe3cbf72020-12-12 22:12:07 -0800900void Vec<T>::reserve(std::size_t new_cap) {
David Tolnayfb6b73c2020-11-10 14:32:16 -0800901 this->reserve_total(new_cap);
902}
903
904template <typename T>
905void Vec<T>::push_back(const T &value) {
906 this->emplace_back(value);
907}
908
909template <typename T>
910void Vec<T>::push_back(T &&value) {
911 this->emplace_back(std::move(value));
912}
913
914template <typename T>
915template <typename... Args>
916void Vec<T>::emplace_back(Args &&... args) {
917 auto size = this->size();
918 this->reserve_total(size + 1);
919 ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
David Tolnaye1df7dd2020-12-27 02:51:51 -0800920 size * size_of<T>()))
David Tolnayfb6b73c2020-11-10 14:32:16 -0800921 T(std::forward<Args>(args)...);
922 this->set_len(size + 1);
923}
924
925template <typename T>
David Tolnay960b5112020-11-25 13:18:28 -0800926typename Vec<T>::iterator Vec<T>::begin() noexcept {
David Tolnay725bf502020-12-27 02:47:40 -0800927 return Slice<T>(this->data(), this->size()).begin();
David Tolnay960b5112020-11-25 13:18:28 -0800928}
929
930template <typename T>
931typename Vec<T>::iterator Vec<T>::end() noexcept {
David Tolnay725bf502020-12-27 02:47:40 -0800932 return Slice<T>(this->data(), this->size()).end();
David Tolnay960b5112020-11-25 13:18:28 -0800933}
934
935template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700936typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
David Tolnay960b5112020-11-25 13:18:28 -0800937 return this->cbegin();
938}
939
940template <typename T>
941typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
942 return this->cend();
943}
944
945template <typename T>
946typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
David Tolnay725bf502020-12-27 02:47:40 -0800947 return Slice<const T>(this->data(), this->size()).begin();
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700948}
949
950template <typename T>
David Tolnay960b5112020-11-25 13:18:28 -0800951typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
David Tolnay725bf502020-12-27 02:47:40 -0800952 return Slice<const T>(this->data(), this->size()).end();
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700953}
954
David Tolnayfec17152021-01-02 12:51:29 -0800955template <typename T>
David Tolnaycf7bb9b2021-01-02 13:03:28 -0800956void Vec<T>::swap(Vec &rhs) noexcept {
David Tolnayfec17152021-01-02 12:51:29 -0800957 using std::swap;
958 swap(this->repr, rhs.repr);
959}
960
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700961// Internal API only intended for the cxxbridge code generator.
962template <typename T>
963Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
David Tolnay0f0162f2020-11-16 23:43:37 -0800964#endif // CXXBRIDGE1_RUST_VEC
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700965
David Tolnay75068632020-12-26 22:15:17 -0800966#ifndef CXXBRIDGE1_IS_COMPLETE
967#define CXXBRIDGE1_IS_COMPLETE
968namespace detail {
969namespace {
970template <typename T, typename = std::size_t>
971struct is_complete : std::false_type {};
972template <typename T>
973struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
974} // namespace
975} // namespace detail
976#endif // CXXBRIDGE1_IS_COMPLETE
977
David Tolnayee6ecfc2020-12-26 21:54:37 -0800978#ifndef CXXBRIDGE1_LAYOUT
979#define CXXBRIDGE1_LAYOUT
980class layout {
981 template <typename T>
982 friend std::size_t size_of();
983 template <typename T>
984 friend std::size_t align_of();
985 template <typename T>
986 static typename std::enable_if<std::is_base_of<Opaque, T>::value,
987 std::size_t>::type
988 do_size_of() {
989 return T::layout::size();
990 }
991 template <typename T>
992 static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
993 std::size_t>::type
994 do_size_of() {
995 return sizeof(T);
996 }
997 template <typename T>
998 static
999 typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
1000 size_of() {
1001 return do_size_of<T>();
1002 }
1003 template <typename T>
1004 static typename std::enable_if<std::is_base_of<Opaque, T>::value,
1005 std::size_t>::type
1006 do_align_of() {
1007 return T::layout::align();
1008 }
1009 template <typename T>
1010 static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
1011 std::size_t>::type
1012 do_align_of() {
1013 return alignof(T);
1014 }
1015 template <typename T>
1016 static
1017 typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
1018 align_of() {
1019 return do_align_of<T>();
1020 }
1021};
1022
1023template <typename T>
1024std::size_t size_of() {
1025 return layout::size_of<T>();
1026}
1027
1028template <typename T>
1029std::size_t align_of() {
1030 return layout::align_of<T>();
1031}
1032#endif // CXXBRIDGE1_LAYOUT
1033
David Tolnay0f0162f2020-11-16 23:43:37 -08001034#ifndef CXXBRIDGE1_RELOCATABLE
1035#define CXXBRIDGE1_RELOCATABLE
David Tolnay174bd952020-11-02 09:23:12 -08001036namespace detail {
1037template <typename... Ts>
1038struct make_void {
1039 using type = void;
1040};
1041
1042template <typename... Ts>
1043using void_t = typename make_void<Ts...>::type;
1044
1045template <typename Void, template <typename...> class, typename...>
1046struct detect : std::false_type {};
1047template <template <typename...> class T, typename... A>
1048struct detect<void_t<T<A...>>, T, A...> : std::true_type {};
1049
1050template <template <typename...> class T, typename... A>
1051using is_detected = detect<void, T, A...>;
1052
1053template <typename T>
1054using detect_IsRelocatable = typename T::IsRelocatable;
1055
1056template <typename T>
1057struct get_IsRelocatable
1058 : std::is_same<typename T::IsRelocatable, std::true_type> {};
1059} // namespace detail
1060
1061template <typename T>
1062struct IsRelocatable
1063 : std::conditional<
1064 detail::is_detected<detail::detect_IsRelocatable, T>::value,
1065 detail::get_IsRelocatable<T>,
1066 std::integral_constant<
1067 bool, std::is_trivially_move_constructible<T>::value &&
1068 std::is_trivially_destructible<T>::value>>::type {};
David Tolnay0f0162f2020-11-16 23:43:37 -08001069#endif // CXXBRIDGE1_RELOCATABLE
David Tolnay174bd952020-11-02 09:23:12 -08001070
David Tolnay0f0162f2020-11-16 23:43:37 -08001071} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -08001072} // namespace rust