blob: 81227868635d58dd964fb11f763a980d308ca420 [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>
Stephen Crane9e48d5b2020-08-21 12:17:02 -07008#include <stdexcept>
David Tolnay7db73692019-10-20 14:51:12 -04009#include <string>
David Tolnayf6292372020-03-01 21:09:11 -080010#include <type_traits>
David Tolnay4791f1c2020-03-17 21:53:16 -070011#include <utility>
David Tolnay37dd7e12020-04-25 12:51:59 -070012#include <vector>
David Tolnay59b5ba12020-04-10 11:32:19 -070013#if defined(_WIN32)
David Tolnayda38b7c2020-09-16 11:50:04 -040014#include <basetsd.h>
David Tolnay59b5ba12020-04-10 11:32:19 -070015#endif
David Tolnay7db73692019-10-20 14:51:12 -040016
David Tolnay750755e2020-03-01 13:04:08 -080017namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080018inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040019
David Tolnay2a2b9ad2020-05-12 20:07:26 -070020struct unsafe_bitcopy_t;
David Tolnayd1e2efc2020-03-03 22:25:43 -080021
David Tolnay84ddf9e2020-10-31 15:36:48 -070022namespace {
23template <typename T>
24class impl;
25}
26
David Tolnay0f0162f2020-11-16 23:43:37 -080027#ifndef CXXBRIDGE1_RUST_STRING
28#define CXXBRIDGE1_RUST_STRING
David Tolnay56082162020-03-01 12:57:33 -080029class String final {
David Tolnay7db73692019-10-20 14:51:12 -040030public:
David Tolnay56082162020-03-01 12:57:33 -080031 String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080032 String(const String &) noexcept;
33 String(String &&) noexcept;
David Tolnay56082162020-03-01 12:57:33 -080034 ~String() noexcept;
David Tolnayd9c4ac92020-03-01 20:33:58 -080035
36 String(const std::string &);
37 String(const char *);
David Tolnayc2bbd952020-07-29 18:15:26 -070038 String(const char *, size_t);
David Tolnayd9c4ac92020-03-01 20:33:58 -080039
40 String &operator=(const String &) noexcept;
41 String &operator=(String &&) noexcept;
42
David Tolnay404d6892020-03-01 20:19:41 -080043 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040044
45 // Note: no null terminator.
46 const char *data() const noexcept;
47 size_t size() const noexcept;
48 size_t length() const noexcept;
49
David Tolnayd1e2efc2020-03-03 22:25:43 -080050 // Internal API only intended for the cxxbridge code generator.
51 String(unsafe_bitcopy_t, const String &) noexcept;
52
David Tolnay7db73692019-10-20 14:51:12 -040053private:
54 // Size and alignment statically verified by rust_string.rs.
55 std::array<uintptr_t, 3> repr;
56};
David Tolnay0f0162f2020-11-16 23:43:37 -080057#endif // CXXBRIDGE1_RUST_STRING
David Tolnay7db73692019-10-20 14:51:12 -040058
David Tolnay0f0162f2020-11-16 23:43:37 -080059#ifndef CXXBRIDGE1_RUST_STR
David Tolnay09dbe752020-03-01 13:00:40 -080060class Str final {
David Tolnay7db73692019-10-20 14:51:12 -040061public:
David Tolnay09dbe752020-03-01 13:00:40 -080062 Str() noexcept;
David Tolnay851677c2020-03-01 23:49:46 -080063 Str(const std::string &);
64 Str(const char *);
David Tolnay894c5e42020-07-29 18:20:00 -070065 Str(const char *, size_t);
David Tolnayd9c4ac92020-03-01 20:33:58 -080066
David Tolnay2d7f1172020-10-31 17:58:31 -070067 Str &operator=(const Str &) noexcept = default;
David Tolnayd9c4ac92020-03-01 20:33:58 -080068
David Tolnay404d6892020-03-01 20:19:41 -080069 explicit operator std::string() const;
David Tolnay7db73692019-10-20 14:51:12 -040070
71 // Note: no null terminator.
72 const char *data() const noexcept;
73 size_t size() const noexcept;
74 size_t length() const noexcept;
75
David Tolnayde9a5b12020-10-31 12:15:43 -070076 // Important in order for System V ABI to pass in registers.
77 Str(const Str &) noexcept = default;
78 ~Str() noexcept = default;
79
David Tolnay5df1f062020-10-31 12:31:10 -070080private:
David Tolnay0356d332020-10-31 19:46:41 -070081 friend impl<Str>;
David Tolnay7db73692019-10-20 14:51:12 -040082 // Not necessarily ABI compatible with &str. Codegen will translate to
83 // cxx::rust_str::RustStr which matches this layout.
David Tolnay5df1f062020-10-31 12:31:10 -070084 const char *ptr;
85 size_t len;
David Tolnay7db73692019-10-20 14:51:12 -040086};
David Tolnay0f0162f2020-11-16 23:43:37 -080087#endif // CXXBRIDGE1_RUST_STR
David Tolnay7db73692019-10-20 14:51:12 -040088
David Tolnay0f0162f2020-11-16 23:43:37 -080089#ifndef CXXBRIDGE1_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -070090template <typename T>
91class Slice final {
David Tolnayce298232020-11-11 10:08:54 -080092 static_assert(std::is_const<T>::value,
93 "&[T] needs to be written as rust::Slice<const T> in C++");
94
David Tolnayefe81052020-04-14 16:28:24 -070095public:
David Tolnay2a2b9ad2020-05-12 20:07:26 -070096 Slice() noexcept;
David Tolnayce298232020-11-11 10:08:54 -080097 Slice(T *, size_t count) noexcept;
David Tolnayefe81052020-04-14 16:28:24 -070098
David Tolnay2d7f1172020-10-31 17:58:31 -070099 Slice &operator=(const Slice<T> &) noexcept = default;
David Tolnayefe81052020-04-14 16:28:24 -0700100
David Tolnayce298232020-11-11 10:08:54 -0800101 T *data() const noexcept;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700102 size_t size() const noexcept;
103 size_t length() const noexcept;
David Tolnayefe81052020-04-14 16:28:24 -0700104
David Tolnayde9a5b12020-10-31 12:15:43 -0700105 // Important in order for System V ABI to pass in registers.
106 Slice(const Slice<T> &) noexcept = default;
107 ~Slice() noexcept = default;
108
David Tolnayefe81052020-04-14 16:28:24 -0700109private:
David Tolnay36aa9e02020-10-31 23:08:21 -0700110 friend impl<Slice>;
111 // Not necessarily ABI compatible with &[T]. Codegen will translate to
112 // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
David Tolnayce298232020-11-11 10:08:54 -0800113 T *ptr;
David Tolnay36aa9e02020-10-31 23:08:21 -0700114 size_t len;
David Tolnayefe81052020-04-14 16:28:24 -0700115};
David Tolnay0f0162f2020-11-16 23:43:37 -0800116#endif // CXXBRIDGE1_RUST_SLICE
David Tolnayefe81052020-04-14 16:28:24 -0700117
David Tolnay0f0162f2020-11-16 23:43:37 -0800118#ifndef CXXBRIDGE1_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 Tolnay0f0162f2020-11-16 23:43:37 -0800157#endif // CXXBRIDGE1_RUST_BOX
David Tolnay7db73692019-10-20 14:51:12 -0400158
David Tolnay0f0162f2020-11-16 23:43:37 -0800159#ifndef CXXBRIDGE1_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 Tolnayfb6b73c2020-11-10 14:32:16 -0800174 T *data() noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700175
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700176 const T &operator[](size_t n) const noexcept;
177 const T &at(size_t n) const;
178
179 const T &front() const;
180 const T &back() const;
181
David Tolnayfb6b73c2020-11-10 14:32:16 -0800182 void reserve(size_t new_cap);
183 void push_back(const T &value);
184 void push_back(T &&value);
David Tolnay4e8c49a2020-11-11 10:00:18 -0800185 template <typename... Args>
David Tolnayfb6b73c2020-11-10 14:32:16 -0800186 void emplace_back(Args &&... args);
187
David Tolnay48521222020-10-31 14:59:42 -0700188 class const_iterator final {
David Tolnayc87c2152020-04-24 17:07:41 -0700189 public:
myronahnda9be502020-04-29 05:47:23 +0700190 using difference_type = ptrdiff_t;
David Tolnayc87c2152020-04-24 17:07:41 -0700191 using value_type = typename std::add_const<T>::type;
David Tolnay74dd3792020-04-30 07:45:24 -0700192 using pointer =
193 typename std::add_pointer<typename std::add_const<T>::type>::type;
David Tolnayc87c2152020-04-24 17:07:41 -0700194 using reference = typename std::add_lvalue_reference<
195 typename std::add_const<T>::type>::type;
myronahnda9be502020-04-29 05:47:23 +0700196 using iterator_category = std::forward_iterator_tag;
David Tolnayc87c2152020-04-24 17:07:41 -0700197
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700198 const T &operator*() const noexcept;
199 const T *operator->() const noexcept;
200 const_iterator &operator++() noexcept;
201 const_iterator operator++(int) noexcept;
202 bool operator==(const const_iterator &) const noexcept;
203 bool operator!=(const const_iterator &) const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700204
205 private:
206 friend class Vec;
207 const void *pos;
208 size_t stride;
209 };
210
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700211 const_iterator begin() const noexcept;
212 const_iterator end() const noexcept;
David Tolnayc87c2152020-04-24 17:07:41 -0700213
David Tolnay313b10e2020-04-25 16:30:51 -0700214 // Internal API only intended for the cxxbridge code generator.
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700215 Vec(unsafe_bitcopy_t, const Vec &) noexcept;
David Tolnay313b10e2020-04-25 16:30:51 -0700216
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700217private:
David Tolnay503d0192020-04-24 22:18:56 -0700218 static size_t stride() noexcept;
David Tolnayfb6b73c2020-11-10 14:32:16 -0800219 void reserve_total(size_t cap) noexcept;
220 void set_len(size_t len) noexcept;
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700221 void drop() noexcept;
222
223 // Size and alignment statically verified by rust_vec.rs.
224 std::array<uintptr_t, 3> repr;
225};
David Tolnay0f0162f2020-11-16 23:43:37 -0800226#endif // CXXBRIDGE1_RUST_VEC
David Tolnay7f2dc3b2020-04-24 16:46:39 -0700227
David Tolnay0f0162f2020-11-16 23:43:37 -0800228#ifndef CXXBRIDGE1_RUST_FN
David Tolnayf262d382020-04-11 22:12:40 -0700229template <typename Signature, bool Throws = false>
230class Fn;
David Tolnay75dca2e2020-03-25 20:17:52 -0700231
232template <typename Ret, typename... Args, bool Throws>
David Tolnay48521222020-10-31 14:59:42 -0700233class Fn<Ret(Args...), Throws> final {
David Tolnay75dca2e2020-03-25 20:17:52 -0700234public:
David Tolnay533d4582020-04-08 20:29:14 -0700235 Ret operator()(Args... args) const noexcept(!Throws);
236 Fn operator*() const noexcept;
David Tolnay75dca2e2020-03-25 20:17:52 -0700237
238private:
239 Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
240 void *fn;
241};
242
David Tolnayf262d382020-04-11 22:12:40 -0700243template <typename Signature>
244using TryFn = Fn<Signature, true>;
David Tolnay0f0162f2020-11-16 23:43:37 -0800245#endif // CXXBRIDGE1_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700246
David Tolnay0f0162f2020-11-16 23:43:37 -0800247#ifndef CXXBRIDGE1_RUST_ERROR
248#define CXXBRIDGE1_RUST_ERROR
David Tolnaye4fa8732020-09-08 15:04:56 -0700249class Error final : public std::exception {
David Tolnay1e548172020-03-16 13:37:09 -0700250public:
251 Error(const Error &);
252 Error(Error &&) noexcept;
David Tolnay2714d2c2020-11-23 18:17:43 -0800253 ~Error() noexcept override;
David Tolnay7c6ac712020-10-31 17:22:28 -0700254
255 Error &operator=(const Error &);
David Tolnay15491062020-10-31 17:25:13 -0700256 Error &operator=(Error &&) noexcept;
David Tolnay7c6ac712020-10-31 17:22:28 -0700257
David Tolnay1e548172020-03-16 13:37:09 -0700258 const char *what() const noexcept override;
259
260private:
David Tolnaya0c9bc72020-10-31 14:37:14 -0700261 Error() noexcept = default;
David Tolnay84ddf9e2020-10-31 15:36:48 -0700262 friend impl<Error>;
David Tolnaya0c9bc72020-10-31 14:37:14 -0700263 const char *msg;
264 size_t len;
David Tolnay1e548172020-03-16 13:37:09 -0700265};
David Tolnay0f0162f2020-11-16 23:43:37 -0800266#endif // CXXBRIDGE1_RUST_ERROR
David Tolnay1e548172020-03-16 13:37:09 -0700267
David Tolnay0f0162f2020-11-16 23:43:37 -0800268#ifndef CXXBRIDGE1_RUST_ISIZE
269#define CXXBRIDGE1_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700270#if defined(_WIN32)
271using isize = SSIZE_T;
272#else
273using isize = ssize_t;
274#endif
David Tolnay0f0162f2020-11-16 23:43:37 -0800275#endif // CXXBRIDGE1_RUST_ISIZE
David Tolnayb8a6fb22020-04-10 11:17:28 -0700276
David Tolnay851677c2020-03-01 23:49:46 -0800277std::ostream &operator<<(std::ostream &, const String &);
278std::ostream &operator<<(std::ostream &, const Str &);
David Tolnay7db73692019-10-20 14:51:12 -0400279
David Tolnay174bd952020-11-02 09:23:12 -0800280// IsRelocatable<T> is used in assertions that a C++ type passed by value
281// between Rust and C++ is soundly relocatable by Rust.
282//
283// There may be legitimate reasons to opt out of the check for support of types
284// that the programmer knows are soundly Rust-movable despite not being
285// recognized as such by the C++ type system due to a move constructor or
286// destructor. To opt out of the relocatability check, do either of the
287// following things in any header used by `include!` in the bridge.
288//
289// --- if you define the type:
290// struct MyType {
291// ...
292// + using IsRelocatable = std::true_type;
293// };
294//
295// --- otherwise:
296// + template <>
297// + struct rust::IsRelocatable<MyType> : std::true_type {};
298template <typename T>
299struct IsRelocatable;
300
David Tolnay3b0c9882020-03-01 14:08:57 -0800301// Snake case aliases for use in code that uses this style for type names.
302using string = String;
303using str = Str;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800304template <typename T>
David Tolnay38c87642020-09-06 22:18:08 -0700305using slice = Slice<T>;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800306template <typename T>
David Tolnayf262d382020-04-11 22:12:40 -0700307using box = Box<T>;
David Tolnay4e8c49a2020-11-11 10:00:18 -0800308template <typename T>
David Tolnay38c87642020-09-06 22:18:08 -0700309using vec = Vec<T>;
David Tolnay1e548172020-03-16 13:37:09 -0700310using error = Error;
David Tolnay75dca2e2020-03-25 20:17:52 -0700311template <typename Signature, bool Throws = false>
312using fn = Fn<Signature, Throws>;
David Tolnayf262d382020-04-11 22:12:40 -0700313template <typename Signature>
314using try_fn = TryFn<Signature>;
David Tolnay174bd952020-11-02 09:23:12 -0800315template <typename T>
316using is_relocatable = IsRelocatable<T>;
David Tolnay3b0c9882020-03-01 14:08:57 -0800317
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700318
319
320////////////////////////////////////////////////////////////////////////////////
321/// end public API, begin implementation details
322
David Tolnay0f0162f2020-11-16 23:43:37 -0800323#ifndef CXXBRIDGE1_PANIC
324#define CXXBRIDGE1_PANIC
David Tolnay521d99d2020-08-26 20:45:40 -0700325template <typename Exception>
326void panic [[noreturn]] (const char *msg);
David Tolnay0f0162f2020-11-16 23:43:37 -0800327#endif // CXXBRIDGE1_PANIC
David Tolnay521d99d2020-08-26 20:45:40 -0700328
David Tolnay0f0162f2020-11-16 23:43:37 -0800329#ifndef CXXBRIDGE1_RUST_FN
330#define CXXBRIDGE1_RUST_FN
David Tolnay75dca2e2020-03-25 20:17:52 -0700331template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700332Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
David Tolnay75dca2e2020-03-25 20:17:52 -0700333 return (*this->trampoline)(std::move(args)..., this->fn);
334}
335
David Tolnaya23129c2020-04-08 20:08:21 -0700336template <typename Ret, typename... Args, bool Throws>
David Tolnay533d4582020-04-08 20:29:14 -0700337Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
David Tolnaya23129c2020-04-08 20:08:21 -0700338 return *this;
339}
David Tolnay0f0162f2020-11-16 23:43:37 -0800340#endif // CXXBRIDGE1_RUST_FN
David Tolnaya23129c2020-04-08 20:08:21 -0700341
David Tolnay0f0162f2020-11-16 23:43:37 -0800342#ifndef CXXBRIDGE1_RUST_BITCOPY
343#define CXXBRIDGE1_RUST_BITCOPY
David Tolnay48521222020-10-31 14:59:42 -0700344struct unsafe_bitcopy_t final {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700345 explicit unsafe_bitcopy_t() = default;
346};
347
348constexpr unsafe_bitcopy_t unsafe_bitcopy{};
David Tolnay0f0162f2020-11-16 23:43:37 -0800349#endif // CXXBRIDGE1_RUST_BITCOPY
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700350
David Tolnay0f0162f2020-11-16 23:43:37 -0800351#ifndef CXXBRIDGE1_RUST_STR
352#define CXXBRIDGE1_RUST_STR
David Tolnay5b1ee1f2020-10-31 18:21:39 -0700353inline const char *Str::data() const noexcept { return this->ptr; }
354
355inline size_t Str::size() const noexcept { return this->len; }
356
357inline size_t Str::length() const noexcept { return this->len; }
David Tolnay0f0162f2020-11-16 23:43:37 -0800358#endif // CXXBRIDGE1_RUST_STR
David Tolnay5b1ee1f2020-10-31 18:21:39 -0700359
David Tolnay0f0162f2020-11-16 23:43:37 -0800360#ifndef CXXBRIDGE1_RUST_SLICE
361#define CXXBRIDGE1_RUST_SLICE
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700362template <typename T>
David Tolnayce298232020-11-11 10:08:54 -0800363Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(this)), len(0) {}
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700364
365template <typename T>
David Tolnayce298232020-11-11 10:08:54 -0800366Slice<T>::Slice(T *s, size_t count) noexcept : ptr(s), len(count) {}
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700367
368template <typename T>
David Tolnayce298232020-11-11 10:08:54 -0800369T *Slice<T>::data() const noexcept {
David Tolnay36aa9e02020-10-31 23:08:21 -0700370 return this->ptr;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700371}
372
373template <typename T>
374size_t Slice<T>::size() const noexcept {
David Tolnay36aa9e02020-10-31 23:08:21 -0700375 return this->len;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700376}
377
378template <typename T>
379size_t Slice<T>::length() const noexcept {
David Tolnay36aa9e02020-10-31 23:08:21 -0700380 return this->len;
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700381}
David Tolnay0f0162f2020-11-16 23:43:37 -0800382#endif // CXXBRIDGE1_RUST_SLICE
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700383
David Tolnay0f0162f2020-11-16 23:43:37 -0800384#ifndef CXXBRIDGE1_RUST_BOX
385#define CXXBRIDGE1_RUST_BOX
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700386template <typename T>
387Box<T>::Box(const Box &other) : Box(*other) {}
388
389template <typename T>
390Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
391 other.ptr = nullptr;
392}
393
394template <typename T>
395Box<T>::Box(const T &val) {
396 this->uninit();
397 ::new (this->ptr) T(val);
398}
399
400template <typename T>
401Box<T>::Box(T &&val) {
402 this->uninit();
403 ::new (this->ptr) T(std::move(val));
404}
405
406template <typename T>
407Box<T>::~Box() noexcept {
408 if (this->ptr) {
409 this->drop();
410 }
411}
412
413template <typename T>
414Box<T> &Box<T>::operator=(const Box &other) {
415 if (this != &other) {
416 if (this->ptr) {
417 **this = *other;
418 } else {
419 this->uninit();
420 ::new (this->ptr) T(*other);
421 }
422 }
423 return *this;
424}
425
426template <typename T>
427Box<T> &Box<T>::operator=(Box &&other) noexcept {
428 if (this->ptr) {
429 this->drop();
430 }
431 this->ptr = other.ptr;
432 other.ptr = nullptr;
433 return *this;
434}
435
436template <typename T>
437const T *Box<T>::operator->() const noexcept {
438 return this->ptr;
439}
440
441template <typename T>
442const T &Box<T>::operator*() const noexcept {
443 return *this->ptr;
444}
445
446template <typename T>
447T *Box<T>::operator->() noexcept {
448 return this->ptr;
449}
450
451template <typename T>
452T &Box<T>::operator*() noexcept {
453 return *this->ptr;
454}
455
456template <typename T>
457template <typename... Fields>
458Box<T> Box<T>::in_place(Fields &&... fields) {
459 Box box;
460 box.uninit();
461 ::new (box.ptr) T{std::forward<Fields>(fields)...};
462 return box;
463}
464
465template <typename T>
466Box<T> Box<T>::from_raw(T *raw) noexcept {
467 Box box;
468 box.ptr = raw;
469 return box;
470}
471
472template <typename T>
473T *Box<T>::into_raw() noexcept {
474 T *raw = this->ptr;
475 this->ptr = nullptr;
476 return raw;
477}
478
479template <typename T>
David Tolnay79076c72020-11-23 18:16:55 -0800480Box<T>::Box() noexcept = default;
David Tolnay0f0162f2020-11-16 23:43:37 -0800481#endif // CXXBRIDGE1_RUST_BOX
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700482
David Tolnay0f0162f2020-11-16 23:43:37 -0800483#ifndef CXXBRIDGE1_RUST_VEC
484#define CXXBRIDGE1_RUST_VEC
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700485template <typename T>
David Tolnay15671862020-11-23 18:13:56 -0800486Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700487 new (&other) Vec();
488}
489
490template <typename T>
491Vec<T>::~Vec() noexcept {
492 this->drop();
493}
494
495template <typename T>
496Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
497 if (this != &other) {
498 this->drop();
499 this->repr = other.repr;
500 new (&other) Vec();
501 }
502 return *this;
503}
504
505template <typename T>
506bool Vec<T>::empty() const noexcept {
507 return size() == 0;
508}
509
510template <typename T>
David Tolnayfb6b73c2020-11-10 14:32:16 -0800511T *Vec<T>::data() noexcept {
512 return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());
513}
514
515template <typename T>
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700516const T &Vec<T>::operator[](size_t n) const noexcept {
517 auto data = reinterpret_cast<const char *>(this->data());
518 return *reinterpret_cast<const T *>(data + n * this->stride());
519}
520
521template <typename T>
522const T &Vec<T>::at(size_t n) const {
David Tolnay8e1e6ac2020-08-26 20:51:43 -0700523 if (n >= this->size()) {
524 panic<std::out_of_range>("rust::Vec index out of range");
525 }
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700526 return (*this)[n];
527}
528
529template <typename T>
530const T &Vec<T>::front() const {
531 return (*this)[0];
532}
533
534template <typename T>
535const T &Vec<T>::back() const {
David Tolnayb10c4bc2020-08-26 21:55:29 -0700536 return (*this)[this->size() - 1];
Stephen Crane9e48d5b2020-08-21 12:17:02 -0700537}
538
539template <typename T>
David Tolnayfb6b73c2020-11-10 14:32:16 -0800540void Vec<T>::reserve(size_t new_cap) {
541 this->reserve_total(new_cap);
542}
543
544template <typename T>
545void Vec<T>::push_back(const T &value) {
546 this->emplace_back(value);
547}
548
549template <typename T>
550void Vec<T>::push_back(T &&value) {
551 this->emplace_back(std::move(value));
552}
553
554template <typename T>
555template <typename... Args>
556void Vec<T>::emplace_back(Args &&... args) {
557 auto size = this->size();
558 this->reserve_total(size + 1);
559 ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
560 size * this->stride()))
561 T(std::forward<Args>(args)...);
562 this->set_len(size + 1);
563}
564
565template <typename T>
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700566const T &Vec<T>::const_iterator::operator*() const noexcept {
567 return *static_cast<const T *>(this->pos);
568}
569
570template <typename T>
571const T *Vec<T>::const_iterator::operator->() const noexcept {
572 return static_cast<const T *>(this->pos);
573}
574
575template <typename T>
576typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
577 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
578 return *this;
579}
580
581template <typename T>
582typename Vec<T>::const_iterator
583Vec<T>::const_iterator::operator++(int) noexcept {
584 auto ret = const_iterator(*this);
585 this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
586 return ret;
587}
588
589template <typename T>
David Tolnayb10c4bc2020-08-26 21:55:29 -0700590bool Vec<T>::const_iterator::operator==(
591 const const_iterator &other) const noexcept {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700592 return this->pos == other.pos;
593}
594
595template <typename T>
David Tolnayb10c4bc2020-08-26 21:55:29 -0700596bool Vec<T>::const_iterator::operator!=(
597 const const_iterator &other) const noexcept {
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700598 return this->pos != other.pos;
599}
600
601template <typename T>
602typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
603 const_iterator it;
604 it.pos = this->data();
605 it.stride = this->stride();
606 return it;
607}
608
609template <typename T>
610typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
611 const_iterator it = this->begin();
612 it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
613 return it;
614}
615
616// Internal API only intended for the cxxbridge code generator.
617template <typename T>
618Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
David Tolnay0f0162f2020-11-16 23:43:37 -0800619#endif // CXXBRIDGE1_RUST_VEC
David Tolnay2a2b9ad2020-05-12 20:07:26 -0700620
David Tolnay0f0162f2020-11-16 23:43:37 -0800621#ifndef CXXBRIDGE1_RELOCATABLE
622#define CXXBRIDGE1_RELOCATABLE
David Tolnay174bd952020-11-02 09:23:12 -0800623namespace detail {
624template <typename... Ts>
625struct make_void {
626 using type = void;
627};
628
629template <typename... Ts>
630using void_t = typename make_void<Ts...>::type;
631
632template <typename Void, template <typename...> class, typename...>
633struct detect : std::false_type {};
634template <template <typename...> class T, typename... A>
635struct detect<void_t<T<A...>>, T, A...> : std::true_type {};
636
637template <template <typename...> class T, typename... A>
638using is_detected = detect<void, T, A...>;
639
640template <typename T>
641using detect_IsRelocatable = typename T::IsRelocatable;
642
643template <typename T>
644struct get_IsRelocatable
645 : std::is_same<typename T::IsRelocatable, std::true_type> {};
646} // namespace detail
647
648template <typename T>
649struct IsRelocatable
650 : std::conditional<
651 detail::is_detected<detail::detect_IsRelocatable, T>::value,
652 detail::get_IsRelocatable<T>,
653 std::integral_constant<
654 bool, std::is_trivially_move_constructible<T>::value &&
655 std::is_trivially_destructible<T>::value>>::type {};
David Tolnay0f0162f2020-11-16 23:43:37 -0800656#endif // CXXBRIDGE1_RELOCATABLE
David Tolnay174bd952020-11-02 09:23:12 -0800657
David Tolnay0f0162f2020-11-16 23:43:37 -0800658} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -0800659} // namespace rust