blob: 6863129ac4fca3611dd0a21f7298ef682ff04f1c [file] [log] [blame]
David Tolnay736cbca2020-03-11 16:49:18 -07001#include "../include/cxx.h"
David Tolnayff86dce2020-11-29 19:45:13 -08002#include <algorithm>
David Tolnay54b13222020-10-30 20:58:32 -07003#include <cassert>
David Tolnay7db73692019-10-20 14:51:12 -04004#include <cstring>
David Tolnay71918ec2020-04-11 21:52:09 -07005#include <exception>
David Tolnay001102a2020-03-01 20:05:04 -08006#include <iostream>
David Tolnay7db73692019-10-20 14:51:12 -04007#include <memory>
8#include <stdexcept>
David Tolnay9ed15c62020-10-31 18:02:03 -07009#include <type_traits>
David Tolnay37dd7e12020-04-25 12:51:59 -070010#include <vector>
David Tolnay7db73692019-10-20 14:51:12 -040011
David Tolnay7db73692019-10-20 14:51:12 -040012extern "C" {
David Tolnaybe3cbf72020-12-12 22:12:07 -080013void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
14 std::size_t len) noexcept {
David Tolnaybb3ff5d2020-11-15 19:45:11 -080015 new (s) std::string(reinterpret_cast<const char *>(ptr), len);
16}
17
David Tolnay0f0162f2020-11-16 23:43:37 -080018void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
David Tolnaybb3ff5d2020-11-15 19:45:11 -080019 using std::string;
20 s->~string();
21}
22
David Tolnay0f0162f2020-11-16 23:43:37 -080023const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040024 return s.data();
25}
26
David Tolnaybe3cbf72020-12-12 22:12:07 -080027std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040028 return s.length();
29}
30
David Tolnaybe3cbf72020-12-12 22:12:07 -080031void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
32 std::size_t len) noexcept {
David Tolnay90691f42020-11-14 20:01:46 -080033 s.append(reinterpret_cast<const char *>(ptr), len);
34}
35
David Tolnay750755e2020-03-01 13:04:08 -080036// rust::String
David Tolnay0f0162f2020-11-16 23:43:37 -080037void cxxbridge1$string$new(rust::String *self) noexcept;
38void cxxbridge1$string$clone(rust::String *self,
39 const rust::String &other) noexcept;
40bool cxxbridge1$string$from(rust::String *self, const char *ptr,
David Tolnaybe3cbf72020-12-12 22:12:07 -080041 std::size_t len) noexcept;
David Tolnay0f0162f2020-11-16 23:43:37 -080042void cxxbridge1$string$drop(rust::String *self) noexcept;
43const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -080044std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
David Tolnaycca2e612020-12-18 12:48:22 -080045void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040046
David Tolnay750755e2020-03-01 13:04:08 -080047// rust::Str
David Tolnaybe3cbf72020-12-12 22:12:07 -080048bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040049} // extern "C"
50
David Tolnay750755e2020-03-01 13:04:08 -080051namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080052inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040053
David Tolnay521d99d2020-08-26 20:45:40 -070054template <typename Exception>
55void panic [[noreturn]] (const char *msg) {
56#if defined(RUST_CXX_NO_EXCEPTIONS)
57 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
58 std::terminate();
59#else
60 throw Exception(msg);
61#endif
62}
63
David Tolnayb10c4bc2020-08-26 21:55:29 -070064template void panic<std::out_of_range>[[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070065
David Tolnay0f0162f2020-11-16 23:43:37 -080066String::String() noexcept { cxxbridge1$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040067
David Tolnay56082162020-03-01 12:57:33 -080068String::String(const String &other) noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -080069 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040070}
71
David Tolnay15671862020-11-23 18:13:56 -080072String::String(String &&other) noexcept : repr(other.repr) {
David Tolnay0f0162f2020-11-16 23:43:37 -080073 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040074}
75
David Tolnay0f0162f2020-11-16 23:43:37 -080076String::~String() noexcept { cxxbridge1$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040077
David Tolnaybe3cbf72020-12-12 22:12:07 -080078static void initString(String *self, const char *s, std::size_t len) {
David Tolnay0f0162f2020-11-16 23:43:37 -080079 if (!cxxbridge1$string$from(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070080 panic<std::invalid_argument>("data for rust::String is not utf-8");
81 }
82}
David Tolnay7db73692019-10-20 14:51:12 -040083
David Tolnay032d8532020-10-30 20:47:31 -070084String::String(const std::string &s) { initString(this, s.data(), s.length()); }
85
David Tolnay54b13222020-10-30 20:58:32 -070086String::String(const char *s) {
87 assert(s != nullptr);
88 initString(this, s, std::strlen(s));
89}
David Tolnayc2bbd952020-07-29 18:15:26 -070090
David Tolnaybe3cbf72020-12-12 22:12:07 -080091String::String(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -070092 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -070093 initString(this,
94 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
95 len);
David Tolnay7db73692019-10-20 14:51:12 -040096}
97
David Tolnay56082162020-03-01 12:57:33 -080098String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040099 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800100 cxxbridge1$string$drop(this);
101 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -0400102 }
103 return *this;
104}
105
David Tolnay56082162020-03-01 12:57:33 -0800106String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400107 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800108 cxxbridge1$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -0400109 this->repr = other.repr;
David Tolnay0f0162f2020-11-16 23:43:37 -0800110 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -0400111 }
112 return *this;
113}
114
David Tolnayd9c4ac92020-03-01 20:33:58 -0800115String::operator std::string() const {
116 return std::string(this->data(), this->size());
117}
118
David Tolnay56082162020-03-01 12:57:33 -0800119const char *String::data() const noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -0800120 return cxxbridge1$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -0400121}
122
David Tolnaybe3cbf72020-12-12 22:12:07 -0800123std::size_t String::size() const noexcept {
124 return cxxbridge1$string$len(this);
125}
David Tolnay7db73692019-10-20 14:51:12 -0400126
David Tolnaybe3cbf72020-12-12 22:12:07 -0800127std::size_t String::length() const noexcept {
128 return cxxbridge1$string$len(this);
129}
David Tolnay7db73692019-10-20 14:51:12 -0400130
David Tolnaycca2e612020-12-18 12:48:22 -0800131const char *String::c_str() noexcept {
132 auto len = this->length();
133 cxxbridge1$string$reserve_total(this, len + 1);
134 auto ptr = this->data();
135 const_cast<char *>(ptr)[len] = '\0';
136 return ptr;
137}
138
David Tolnayff7f5fb2020-11-25 20:50:32 -0800139String::iterator String::begin() noexcept {
140 return const_cast<char *>(this->data());
141}
142
143String::iterator String::end() noexcept {
144 return const_cast<char *>(this->data()) + this->size();
145}
146
147String::const_iterator String::begin() const noexcept { return this->cbegin(); }
148
149String::const_iterator String::end() const noexcept { return this->cend(); }
150
151String::const_iterator String::cbegin() const noexcept { return this->data(); }
152
153String::const_iterator String::cend() const noexcept {
154 return this->data() + this->size();
155}
156
David Tolnayff86dce2020-11-29 19:45:13 -0800157bool String::operator==(const String &rhs) const noexcept {
158 return rust::Str(*this) == rust::Str(rhs);
159}
160
161bool String::operator!=(const String &rhs) const noexcept {
162 return rust::Str(*this) != rust::Str(rhs);
163}
164
165bool String::operator<(const String &rhs) const noexcept {
166 return rust::Str(*this) < rust::Str(rhs);
167}
168
169bool String::operator<=(const String &rhs) const noexcept {
170 return rust::Str(*this) <= rust::Str(rhs);
171}
172
173bool String::operator>(const String &rhs) const noexcept {
174 return rust::Str(*this) > rust::Str(rhs);
175}
176
177bool String::operator>=(const String &rhs) const noexcept {
178 return rust::Str(*this) >= rust::Str(rhs);
179}
180
David Tolnayd1e2efc2020-03-03 22:25:43 -0800181String::String(unsafe_bitcopy_t, const String &bits) noexcept
182 : repr(bits.repr) {}
183
David Tolnay56082162020-03-01 12:57:33 -0800184std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400185 os.write(s.data(), s.size());
186 return os;
187}
188
David Tolnay5df1f062020-10-31 12:31:10 -0700189Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
David Tolnay7db73692019-10-20 14:51:12 -0400190
David Tolnay828e5132020-11-29 20:40:40 -0800191Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
192
David Tolnaybe3cbf72020-12-12 22:12:07 -0800193static void initStr(const char *ptr, std::size_t len) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800194 if (!cxxbridge1$str$valid(ptr, len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700195 panic<std::invalid_argument>("data for rust::Str is not utf-8");
196 }
197}
David Tolnay7db73692019-10-20 14:51:12 -0400198
David Tolnay5df1f062020-10-31 12:31:10 -0700199Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
200 initStr(this->ptr, this->len);
David Tolnay8d323662020-10-30 19:32:26 -0700201}
David Tolnay894c5e42020-07-29 18:20:00 -0700202
David Tolnay5df1f062020-10-31 12:31:10 -0700203Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
David Tolnay54b13222020-10-30 20:58:32 -0700204 assert(s != nullptr);
David Tolnay5df1f062020-10-31 12:31:10 -0700205 initStr(this->ptr, this->len);
David Tolnay54b13222020-10-30 20:58:32 -0700206}
David Tolnay032d8532020-10-30 20:47:31 -0700207
David Tolnaybe3cbf72020-12-12 22:12:07 -0800208Str::Str(const char *s, std::size_t len)
David Tolnay5df1f062020-10-31 12:31:10 -0700209 : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
210 len(len) {
David Tolnay54b13222020-10-30 20:58:32 -0700211 assert(s != nullptr || len == 0);
David Tolnay5df1f062020-10-31 12:31:10 -0700212 initStr(this->ptr, this->len);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800213}
David Tolnay7db73692019-10-20 14:51:12 -0400214
David Tolnay09dbe752020-03-01 13:00:40 -0800215Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400216 return std::string(this->data(), this->size());
217}
218
David Tolnayff7f5fb2020-11-25 20:50:32 -0800219Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
220
221Str::const_iterator Str::end() const noexcept { return this->cend(); }
222
223Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
224
225Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
226
David Tolnayff86dce2020-11-29 19:45:13 -0800227bool Str::operator==(const Str &rhs) const noexcept {
228 return this->len == rhs.len &&
229 std::equal(this->begin(), this->end(), rhs.begin());
230}
231
232bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
233
234bool Str::operator<(const Str &rhs) const noexcept {
235 return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
236 rhs.end());
237}
238
239bool Str::operator<=(const Str &rhs) const noexcept {
240 // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
241 // without Undefined Behavior on C++11 if rhs is shorter than *this.
242 const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
243 rend = rhs.end();
244 while (liter != lend && riter != rend && *liter == *riter) {
245 ++liter, ++riter;
246 }
247 if (liter == lend) {
248 return true; // equal or *this is a prefix of rhs
249 } else if (riter == rend) {
250 return false; // rhs is a prefix of *this
251 } else {
252 return *liter <= *riter;
253 }
254}
255
256bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
257
258bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
259
David Tolnay09dbe752020-03-01 13:00:40 -0800260std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400261 os.write(s.data(), s.size());
262 return os;
263}
264
David Tolnay03c43f52020-12-12 21:07:17 -0800265// Rust specifies that usize is ABI compatible with C's uintptr_t.
266// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
267// However there is no direct Rust equivalent for size_t. C does not guarantee
268// that size_t and uintptr_t are compatible. In practice though, on all
269// platforms supported by Rust, they are identical for ABI purposes. See the
270// libc crate which unconditionally defines libc::size_t = usize. We expect the
271// same here and these assertions are just here to explicitly document that.
272// *Note that no assumption is made about C++ name mangling of signatures
273// containing these types, not here nor anywhere in CXX.*
David Tolnaybe3cbf72020-12-12 22:12:07 -0800274static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
275 "unsupported size_t size");
276static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800277 "unsupported size_t alignment");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800278static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800279 "unsupported ssize_t size");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800280static_assert(alignof(rust::isize) == alignof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800281 "unsupported ssize_t alignment");
282
David Tolnay9ed15c62020-10-31 18:02:03 -0700283static_assert(std::is_trivially_copy_constructible<Str>::value,
284 "trivial Str(const Str &)");
285static_assert(std::is_trivially_copy_assignable<Str>::value,
286 "trivial operator=(const Str &)");
287static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
288
David Tolnay9578cf12020-11-25 14:36:46 -0800289static_assert(
David Tolnaybe3cbf72020-12-12 22:12:07 -0800290 std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
291 "trivial Slice(const Slice &)");
292static_assert(
293 std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
294 "trivial Slice(Slice &&)");
295static_assert(
296 std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
297 "trivial Slice::operator=(const Slice &) for const slices");
298static_assert(
299 std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
300 "trivial Slice::operator=(Slice &&)");
301static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
302 "trivial ~Slice()");
303
304static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
305 "trivial Slice(const Slice &)");
306static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
307 "trivial Slice(Slice &&)");
308static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
309 "delete Slice::operator=(const Slice &) for mut slices");
310static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
311 "trivial Slice::operator=(Slice &&)");
312static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
313 "trivial ~Slice()");
314
315static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
316 Vec<const std::uint8_t>::iterator>::value,
317 "Vec<T>::const_iterator == Vec<const T>::iterator");
318static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
319 Vec<const std::uint8_t>::iterator>::value,
320 "Vec<const T>::const_iterator == Vec<const T>::iterator");
321static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
322 Vec<std::uint8_t>::iterator>::value,
323 "Vec<T>::const_iterator != Vec<T>::iterator");
David Tolnay9578cf12020-11-25 14:36:46 -0800324
David Tolnay1e548172020-03-16 13:37:09 -0700325extern "C" {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800326const char *cxxbridge1$error(const char *ptr, std::size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700327 char *copy = new char[len];
David Tolnay504cf3c2020-10-31 16:08:04 -0700328 std::strncpy(copy, ptr, len);
David Tolnay1e548172020-03-16 13:37:09 -0700329 return copy;
330}
331} // extern "C"
332
David Tolnayd5712ee2020-10-31 17:10:00 -0700333Error::Error(const Error &other)
David Tolnay0f0162f2020-11-16 23:43:37 -0800334 : std::exception(other), msg(cxxbridge1$error(other.msg, other.len)),
David Tolnay23c23192020-10-31 17:11:48 -0700335 len(other.len) {}
David Tolnay1e548172020-03-16 13:37:09 -0700336
David Tolnay23c23192020-10-31 17:11:48 -0700337Error::Error(Error &&other) noexcept
338 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
David Tolnaya0c9bc72020-10-31 14:37:14 -0700339 other.msg = nullptr;
340 other.len = 0;
David Tolnay1e548172020-03-16 13:37:09 -0700341}
342
David Tolnaya0c9bc72020-10-31 14:37:14 -0700343Error::~Error() noexcept { delete[] this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700344
David Tolnay7c6ac712020-10-31 17:22:28 -0700345Error &Error::operator=(const Error &other) {
346 if (this != &other) {
347 std::exception::operator=(other);
348 delete[] this->msg;
349 this->msg = nullptr;
David Tolnay0f0162f2020-11-16 23:43:37 -0800350 this->msg = cxxbridge1$error(other.msg, other.len);
David Tolnay7c6ac712020-10-31 17:22:28 -0700351 this->len = other.len;
352 }
353 return *this;
354}
355
David Tolnay15491062020-10-31 17:25:13 -0700356Error &Error::operator=(Error &&other) noexcept {
357 if (this != &other) {
358 std::exception::operator=(std::move(other));
359 this->msg = other.msg;
360 this->len = other.len;
361 other.msg = nullptr;
362 other.len = 0;
363 }
364 return *this;
365}
366
David Tolnaya0c9bc72020-10-31 14:37:14 -0700367const char *Error::what() const noexcept { return this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700368
David Tolnay5b163402020-12-10 19:26:02 -0800369namespace {
370template <typename T>
371union MaybeUninit {
372 T value;
373 MaybeUninit() {}
374 ~MaybeUninit() {}
375};
376} // namespace
377
David Tolnay0f0162f2020-11-16 23:43:37 -0800378} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -0800379} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400380
381extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800382void cxxbridge1$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400383 std::unique_ptr<std::string> *ptr) noexcept {
384 new (ptr) std::unique_ptr<std::string>();
385}
David Tolnay0f0162f2020-11-16 23:43:37 -0800386void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
387 std::string *raw) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400388 new (ptr) std::unique_ptr<std::string>(raw);
389}
David Tolnay0f0162f2020-11-16 23:43:37 -0800390const std::string *cxxbridge1$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400391 const std::unique_ptr<std::string> &ptr) noexcept {
392 return ptr.get();
393}
David Tolnay0f0162f2020-11-16 23:43:37 -0800394std::string *cxxbridge1$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400395 std::unique_ptr<std::string> &ptr) noexcept {
396 return ptr.release();
397}
David Tolnay0f0162f2020-11-16 23:43:37 -0800398void cxxbridge1$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400399 std::unique_ptr<std::string> *ptr) noexcept {
400 ptr->~unique_ptr();
401}
402} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700403
David Tolnay06677b32020-11-23 18:05:45 -0800404namespace {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800405const std::size_t kMaxExpectedWordsInString = 8;
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800406static_assert(alignof(std::string) <= alignof(void *),
407 "unexpectedly large std::string alignment");
David Tolnay06677b32020-11-23 18:05:45 -0800408static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800409 "unexpectedly large std::string size");
David Tolnayc26de542020-11-23 18:18:19 -0800410} // namespace
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800411
David Tolnay37dd7e12020-04-25 12:51:59 -0700412#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800413 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700414 const std::vector<CXX_TYPE> &s) noexcept { \
415 return s.size(); \
416 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800417 const CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800418 const std::vector<CXX_TYPE> &s, std::size_t pos) noexcept { \
David Tolnay9626d082020-04-24 14:52:45 -0700419 return &s[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700420 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800421 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700422 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
423 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700424 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800425 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700426 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700427 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700428 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700429 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700430 const std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800431 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700432 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700433 return ptr.get(); \
434 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700435 std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800436 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700437 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700438 return ptr.release(); \
439 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800440 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700441 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700442 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700443 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700444
David Tolnay6787be62020-04-25 11:01:02 -0700445#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay0f0162f2020-11-16 23:43:37 -0800446 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700447 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800448 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700449 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800450 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700451 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800452 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
David Tolnaydc62d712020-12-11 13:51:53 -0800453 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800454 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700455 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800456 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800457 rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800458 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800459 std::size_t len) noexcept; \
460 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700461
462#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
463 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700464 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800465 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700466 } \
467 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700468 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800469 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700470 } \
471 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800472 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800473 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700474 } \
475 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800476 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
David Tolnaydc62d712020-12-11 13:51:53 -0800477 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
478 } \
479 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700480 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800481 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700482 } \
483 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800484 void Vec<CXX_TYPE>::reserve_total(std::size_t cap) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800485 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, cap); \
David Tolnayfb6b73c2020-11-10 14:32:16 -0800486 } \
487 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800488 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800489 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
David Tolnayfb6b73c2020-11-10 14:32:16 -0800490 } \
491 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800492 std::size_t Vec<CXX_TYPE>::stride() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800493 return cxxbridge1$rust_vec$##RUST_TYPE##$stride(); \
David Tolnay6787be62020-04-25 11:01:02 -0700494 }
495
David Tolnay5b163402020-12-10 19:26:02 -0800496#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
497 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
498 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
499 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
500 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
501 new (ptr) std::shared_ptr<CXX_TYPE>(); \
502 } \
503 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
504 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
505 CXX_TYPE *uninit = \
506 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
507 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
508 return uninit; \
509 } \
510 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
511 const std::shared_ptr<CXX_TYPE> &self, \
512 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
513 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
514 } \
515 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
516 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
517 return self.get(); \
518 } \
519 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
520 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
521 self->~shared_ptr(); \
522 }
523
David Tolnay6787be62020-04-25 11:01:02 -0700524// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700525#define FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800526 MACRO(u8, std::uint8_t) \
527 MACRO(u16, std::uint16_t) \
528 MACRO(u32, std::uint32_t) \
529 MACRO(u64, std::uint64_t) \
530 MACRO(i8, std::int8_t) \
531 MACRO(i16, std::int16_t) \
532 MACRO(i32, std::int32_t) \
533 MACRO(i64, std::int64_t) \
David Tolnay6787be62020-04-25 11:01:02 -0700534 MACRO(f32, float) \
535 MACRO(f64, double)
536
David Tolnayf336b3b2020-04-30 08:45:54 -0700537#define FOR_EACH_STD_VECTOR(MACRO) \
538 FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800539 MACRO(usize, std::size_t) \
David Tolnay47e239d2020-08-28 00:32:04 -0700540 MACRO(isize, rust::isize) \
541 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700542
David Tolnayf336b3b2020-04-30 08:45:54 -0700543#define FOR_EACH_RUST_VEC(MACRO) \
544 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700545 MACRO(bool, bool) \
David Tolnay93e71d02020-11-25 20:16:52 -0800546 MACRO(char, char) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700547 MACRO(string, rust::String)
David Tolnayf336b3b2020-04-30 08:45:54 -0700548
David Tolnay5b163402020-12-10 19:26:02 -0800549#define FOR_EACH_SHARED_PTR(MACRO) \
550 FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800551 MACRO(usize, std::size_t) \
David Tolnay5b163402020-12-10 19:26:02 -0800552 MACRO(isize, rust::isize) \
553 MACRO(string, std::string)
554
David Tolnay4e7e7c42020-04-24 14:48:07 -0700555extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700556FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
557FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay5b163402020-12-10 19:26:02 -0800558FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700559} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700560
David Tolnay1768d8f2020-04-25 18:15:11 -0700561namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -0800562inline namespace cxxbridge1 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700563FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay0f0162f2020-11-16 23:43:37 -0800564} // namespace cxxbridge1
David Tolnay1768d8f2020-04-25 18:15:11 -0700565} // namespace rust