blob: f9d7fad5eb6424a30d342ef20ca093d8efbdf909 [file] [log] [blame]
David Tolnay736cbca2020-03-11 16:49:18 -07001#include "../include/cxx.h"
David Tolnay7db73692019-10-20 14:51:12 -04002#include <cstring>
David Tolnay001102a2020-03-01 20:05:04 -08003#include <iostream>
David Tolnay7db73692019-10-20 14:51:12 -04004#include <memory>
David Tolnay7db73692019-10-20 14:51:12 -04005
David Tolnay7db73692019-10-20 14:51:12 -04006extern "C" {
David Tolnaybe3cbf72020-12-12 22:12:07 -08007void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
8 std::size_t len) noexcept {
David Tolnaybb3ff5d2020-11-15 19:45:11 -08009 new (s) std::string(reinterpret_cast<const char *>(ptr), len);
10}
11
David Tolnay0f0162f2020-11-16 23:43:37 -080012void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
David Tolnaybb3ff5d2020-11-15 19:45:11 -080013 using std::string;
14 s->~string();
15}
16
David Tolnay0f0162f2020-11-16 23:43:37 -080017const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040018 return s.data();
19}
20
David Tolnaybe3cbf72020-12-12 22:12:07 -080021std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040022 return s.length();
23}
24
David Tolnaybe3cbf72020-12-12 22:12:07 -080025void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
26 std::size_t len) noexcept {
David Tolnay90691f42020-11-14 20:01:46 -080027 s.append(reinterpret_cast<const char *>(ptr), len);
28}
29
David Tolnay750755e2020-03-01 13:04:08 -080030// rust::String
David Tolnay0f0162f2020-11-16 23:43:37 -080031void cxxbridge1$string$new(rust::String *self) noexcept;
32void cxxbridge1$string$clone(rust::String *self,
33 const rust::String &other) noexcept;
34bool cxxbridge1$string$from(rust::String *self, const char *ptr,
David Tolnaybe3cbf72020-12-12 22:12:07 -080035 std::size_t len) noexcept;
David Tolnay0f0162f2020-11-16 23:43:37 -080036void cxxbridge1$string$drop(rust::String *self) noexcept;
37const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -080038std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
David Tolnaycca2e612020-12-18 12:48:22 -080039void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040040
David Tolnay750755e2020-03-01 13:04:08 -080041// rust::Str
David Tolnaybe3cbf72020-12-12 22:12:07 -080042bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040043} // extern "C"
44
David Tolnay750755e2020-03-01 13:04:08 -080045namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080046inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040047
David Tolnay521d99d2020-08-26 20:45:40 -070048template <typename Exception>
49void panic [[noreturn]] (const char *msg) {
50#if defined(RUST_CXX_NO_EXCEPTIONS)
51 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
52 std::terminate();
53#else
54 throw Exception(msg);
55#endif
56}
57
David Tolnayb10c4bc2020-08-26 21:55:29 -070058template void panic<std::out_of_range>[[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070059
David Tolnay0f0162f2020-11-16 23:43:37 -080060String::String() noexcept { cxxbridge1$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040061
David Tolnay56082162020-03-01 12:57:33 -080062String::String(const String &other) noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -080063 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040064}
65
David Tolnay15671862020-11-23 18:13:56 -080066String::String(String &&other) noexcept : repr(other.repr) {
David Tolnay0f0162f2020-11-16 23:43:37 -080067 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040068}
69
David Tolnay0f0162f2020-11-16 23:43:37 -080070String::~String() noexcept { cxxbridge1$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040071
David Tolnaybe3cbf72020-12-12 22:12:07 -080072static void initString(String *self, const char *s, std::size_t len) {
David Tolnay0f0162f2020-11-16 23:43:37 -080073 if (!cxxbridge1$string$from(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070074 panic<std::invalid_argument>("data for rust::String is not utf-8");
75 }
76}
David Tolnay7db73692019-10-20 14:51:12 -040077
David Tolnay032d8532020-10-30 20:47:31 -070078String::String(const std::string &s) { initString(this, s.data(), s.length()); }
79
David Tolnay54b13222020-10-30 20:58:32 -070080String::String(const char *s) {
81 assert(s != nullptr);
82 initString(this, s, std::strlen(s));
83}
David Tolnayc2bbd952020-07-29 18:15:26 -070084
David Tolnaybe3cbf72020-12-12 22:12:07 -080085String::String(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -070086 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -070087 initString(this,
88 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
89 len);
David Tolnay7db73692019-10-20 14:51:12 -040090}
91
David Tolnay56082162020-03-01 12:57:33 -080092String &String::operator=(const String &other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -040093 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -080094 cxxbridge1$string$drop(this);
95 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040096 }
97 return *this;
98}
99
David Tolnay56082162020-03-01 12:57:33 -0800100String &String::operator=(String &&other) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400101 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800102 cxxbridge1$string$drop(this);
David Tolnay7db73692019-10-20 14:51:12 -0400103 this->repr = other.repr;
David Tolnay0f0162f2020-11-16 23:43:37 -0800104 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -0400105 }
106 return *this;
107}
108
David Tolnayd9c4ac92020-03-01 20:33:58 -0800109String::operator std::string() const {
110 return std::string(this->data(), this->size());
111}
112
David Tolnay56082162020-03-01 12:57:33 -0800113const char *String::data() const noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -0800114 return cxxbridge1$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -0400115}
116
David Tolnaybe3cbf72020-12-12 22:12:07 -0800117std::size_t String::size() const noexcept {
118 return cxxbridge1$string$len(this);
119}
David Tolnay7db73692019-10-20 14:51:12 -0400120
David Tolnaybe3cbf72020-12-12 22:12:07 -0800121std::size_t String::length() const noexcept {
122 return cxxbridge1$string$len(this);
123}
David Tolnay7db73692019-10-20 14:51:12 -0400124
David Tolnaycca2e612020-12-18 12:48:22 -0800125const char *String::c_str() noexcept {
126 auto len = this->length();
127 cxxbridge1$string$reserve_total(this, len + 1);
128 auto ptr = this->data();
129 const_cast<char *>(ptr)[len] = '\0';
130 return ptr;
131}
132
David Tolnayff7f5fb2020-11-25 20:50:32 -0800133String::iterator String::begin() noexcept {
134 return const_cast<char *>(this->data());
135}
136
137String::iterator String::end() noexcept {
138 return const_cast<char *>(this->data()) + this->size();
139}
140
141String::const_iterator String::begin() const noexcept { return this->cbegin(); }
142
143String::const_iterator String::end() const noexcept { return this->cend(); }
144
145String::const_iterator String::cbegin() const noexcept { return this->data(); }
146
147String::const_iterator String::cend() const noexcept {
148 return this->data() + this->size();
149}
150
David Tolnayff86dce2020-11-29 19:45:13 -0800151bool String::operator==(const String &rhs) const noexcept {
152 return rust::Str(*this) == rust::Str(rhs);
153}
154
155bool String::operator!=(const String &rhs) const noexcept {
156 return rust::Str(*this) != rust::Str(rhs);
157}
158
159bool String::operator<(const String &rhs) const noexcept {
160 return rust::Str(*this) < rust::Str(rhs);
161}
162
163bool String::operator<=(const String &rhs) const noexcept {
164 return rust::Str(*this) <= rust::Str(rhs);
165}
166
167bool String::operator>(const String &rhs) const noexcept {
168 return rust::Str(*this) > rust::Str(rhs);
169}
170
171bool String::operator>=(const String &rhs) const noexcept {
172 return rust::Str(*this) >= rust::Str(rhs);
173}
174
David Tolnayfec17152021-01-02 12:51:29 -0800175void String::swap(String &rhs) noexcept {
176 using std::swap;
177 swap(this->repr, rhs.repr);
178}
179
David Tolnayd1e2efc2020-03-03 22:25:43 -0800180String::String(unsafe_bitcopy_t, const String &bits) noexcept
181 : repr(bits.repr) {}
182
David Tolnay56082162020-03-01 12:57:33 -0800183std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400184 os.write(s.data(), s.size());
185 return os;
186}
187
David Tolnay5df1f062020-10-31 12:31:10 -0700188Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
David Tolnay7db73692019-10-20 14:51:12 -0400189
David Tolnay828e5132020-11-29 20:40:40 -0800190Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
191
David Tolnaybe3cbf72020-12-12 22:12:07 -0800192static void initStr(const char *ptr, std::size_t len) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800193 if (!cxxbridge1$str$valid(ptr, len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700194 panic<std::invalid_argument>("data for rust::Str is not utf-8");
195 }
196}
David Tolnay7db73692019-10-20 14:51:12 -0400197
David Tolnay5df1f062020-10-31 12:31:10 -0700198Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
199 initStr(this->ptr, this->len);
David Tolnay8d323662020-10-30 19:32:26 -0700200}
David Tolnay894c5e42020-07-29 18:20:00 -0700201
David Tolnay5df1f062020-10-31 12:31:10 -0700202Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
David Tolnay54b13222020-10-30 20:58:32 -0700203 assert(s != nullptr);
David Tolnay5df1f062020-10-31 12:31:10 -0700204 initStr(this->ptr, this->len);
David Tolnay54b13222020-10-30 20:58:32 -0700205}
David Tolnay032d8532020-10-30 20:47:31 -0700206
David Tolnaybe3cbf72020-12-12 22:12:07 -0800207Str::Str(const char *s, std::size_t len)
David Tolnay5df1f062020-10-31 12:31:10 -0700208 : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
209 len(len) {
David Tolnay54b13222020-10-30 20:58:32 -0700210 assert(s != nullptr || len == 0);
David Tolnay5df1f062020-10-31 12:31:10 -0700211 initStr(this->ptr, this->len);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800212}
David Tolnay7db73692019-10-20 14:51:12 -0400213
David Tolnay09dbe752020-03-01 13:00:40 -0800214Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400215 return std::string(this->data(), this->size());
216}
217
David Tolnayff7f5fb2020-11-25 20:50:32 -0800218Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
219
220Str::const_iterator Str::end() const noexcept { return this->cend(); }
221
222Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
223
224Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
225
David Tolnayff86dce2020-11-29 19:45:13 -0800226bool Str::operator==(const Str &rhs) const noexcept {
227 return this->len == rhs.len &&
228 std::equal(this->begin(), this->end(), rhs.begin());
229}
230
231bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
232
233bool Str::operator<(const Str &rhs) const noexcept {
234 return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
235 rhs.end());
236}
237
238bool Str::operator<=(const Str &rhs) const noexcept {
239 // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
240 // without Undefined Behavior on C++11 if rhs is shorter than *this.
241 const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
242 rend = rhs.end();
243 while (liter != lend && riter != rend && *liter == *riter) {
244 ++liter, ++riter;
245 }
246 if (liter == lend) {
247 return true; // equal or *this is a prefix of rhs
248 } else if (riter == rend) {
249 return false; // rhs is a prefix of *this
250 } else {
251 return *liter <= *riter;
252 }
253}
254
255bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
256
257bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
258
David Tolnay09dbe752020-03-01 13:00:40 -0800259std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400260 os.write(s.data(), s.size());
261 return os;
262}
263
David Tolnay03c43f52020-12-12 21:07:17 -0800264// Rust specifies that usize is ABI compatible with C's uintptr_t.
265// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
266// However there is no direct Rust equivalent for size_t. C does not guarantee
267// that size_t and uintptr_t are compatible. In practice though, on all
268// platforms supported by Rust, they are identical for ABI purposes. See the
269// libc crate which unconditionally defines libc::size_t = usize. We expect the
270// same here and these assertions are just here to explicitly document that.
271// *Note that no assumption is made about C++ name mangling of signatures
272// containing these types, not here nor anywhere in CXX.*
David Tolnaybe3cbf72020-12-12 22:12:07 -0800273static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
274 "unsupported size_t size");
275static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800276 "unsupported size_t alignment");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800277static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800278 "unsupported ssize_t size");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800279static_assert(alignof(rust::isize) == alignof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800280 "unsupported ssize_t alignment");
281
David Tolnay9ed15c62020-10-31 18:02:03 -0700282static_assert(std::is_trivially_copy_constructible<Str>::value,
283 "trivial Str(const Str &)");
284static_assert(std::is_trivially_copy_assignable<Str>::value,
285 "trivial operator=(const Str &)");
286static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
287
David Tolnay9578cf12020-11-25 14:36:46 -0800288static_assert(
David Tolnaybe3cbf72020-12-12 22:12:07 -0800289 std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
290 "trivial Slice(const Slice &)");
291static_assert(
292 std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
293 "trivial Slice(Slice &&)");
294static_assert(
295 std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
296 "trivial Slice::operator=(const Slice &) for const slices");
297static_assert(
298 std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
299 "trivial Slice::operator=(Slice &&)");
300static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
301 "trivial ~Slice()");
302
303static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
304 "trivial Slice(const Slice &)");
305static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
306 "trivial Slice(Slice &&)");
307static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
308 "delete Slice::operator=(const Slice &) for mut slices");
309static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
310 "trivial Slice::operator=(Slice &&)");
311static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
312 "trivial ~Slice()");
313
314static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
315 Vec<const std::uint8_t>::iterator>::value,
316 "Vec<T>::const_iterator == Vec<const T>::iterator");
317static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
318 Vec<const std::uint8_t>::iterator>::value,
319 "Vec<const T>::const_iterator == Vec<const T>::iterator");
320static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
321 Vec<std::uint8_t>::iterator>::value,
322 "Vec<T>::const_iterator != Vec<T>::iterator");
David Tolnay9578cf12020-11-25 14:36:46 -0800323
David Tolnay1e548172020-03-16 13:37:09 -0700324extern "C" {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800325const char *cxxbridge1$error(const char *ptr, std::size_t len) {
David Tolnay1e548172020-03-16 13:37:09 -0700326 char *copy = new char[len];
David Tolnay504cf3c2020-10-31 16:08:04 -0700327 std::strncpy(copy, ptr, len);
David Tolnay1e548172020-03-16 13:37:09 -0700328 return copy;
329}
330} // extern "C"
331
David Tolnayd5712ee2020-10-31 17:10:00 -0700332Error::Error(const Error &other)
David Tolnay0f0162f2020-11-16 23:43:37 -0800333 : std::exception(other), msg(cxxbridge1$error(other.msg, other.len)),
David Tolnay23c23192020-10-31 17:11:48 -0700334 len(other.len) {}
David Tolnay1e548172020-03-16 13:37:09 -0700335
David Tolnay23c23192020-10-31 17:11:48 -0700336Error::Error(Error &&other) noexcept
337 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
David Tolnaya0c9bc72020-10-31 14:37:14 -0700338 other.msg = nullptr;
339 other.len = 0;
David Tolnay1e548172020-03-16 13:37:09 -0700340}
341
David Tolnaya0c9bc72020-10-31 14:37:14 -0700342Error::~Error() noexcept { delete[] this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700343
David Tolnay7c6ac712020-10-31 17:22:28 -0700344Error &Error::operator=(const Error &other) {
345 if (this != &other) {
346 std::exception::operator=(other);
347 delete[] this->msg;
348 this->msg = nullptr;
David Tolnay0f0162f2020-11-16 23:43:37 -0800349 this->msg = cxxbridge1$error(other.msg, other.len);
David Tolnay7c6ac712020-10-31 17:22:28 -0700350 this->len = other.len;
351 }
352 return *this;
353}
354
David Tolnay15491062020-10-31 17:25:13 -0700355Error &Error::operator=(Error &&other) noexcept {
356 if (this != &other) {
357 std::exception::operator=(std::move(other));
358 this->msg = other.msg;
359 this->len = other.len;
360 other.msg = nullptr;
361 other.len = 0;
362 }
363 return *this;
364}
365
David Tolnaya0c9bc72020-10-31 14:37:14 -0700366const char *Error::what() const noexcept { return this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700367
David Tolnay5b163402020-12-10 19:26:02 -0800368namespace {
369template <typename T>
370union MaybeUninit {
371 T value;
372 MaybeUninit() {}
373 ~MaybeUninit() {}
374};
375} // namespace
376
David Tolnay0f0162f2020-11-16 23:43:37 -0800377} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -0800378} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400379
380extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800381void cxxbridge1$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400382 std::unique_ptr<std::string> *ptr) noexcept {
383 new (ptr) std::unique_ptr<std::string>();
384}
David Tolnay0f0162f2020-11-16 23:43:37 -0800385void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
386 std::string *raw) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400387 new (ptr) std::unique_ptr<std::string>(raw);
388}
David Tolnay0f0162f2020-11-16 23:43:37 -0800389const std::string *cxxbridge1$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400390 const std::unique_ptr<std::string> &ptr) noexcept {
391 return ptr.get();
392}
David Tolnay0f0162f2020-11-16 23:43:37 -0800393std::string *cxxbridge1$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400394 std::unique_ptr<std::string> &ptr) noexcept {
395 return ptr.release();
396}
David Tolnay0f0162f2020-11-16 23:43:37 -0800397void cxxbridge1$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400398 std::unique_ptr<std::string> *ptr) noexcept {
399 ptr->~unique_ptr();
400}
401} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700402
David Tolnay06677b32020-11-23 18:05:45 -0800403namespace {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800404const std::size_t kMaxExpectedWordsInString = 8;
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800405static_assert(alignof(std::string) <= alignof(void *),
406 "unexpectedly large std::string alignment");
David Tolnay06677b32020-11-23 18:05:45 -0800407static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800408 "unexpectedly large std::string size");
David Tolnayc26de542020-11-23 18:18:19 -0800409} // namespace
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800410
David Tolnay37dd7e12020-04-25 12:51:59 -0700411#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800412 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700413 const std::vector<CXX_TYPE> &s) noexcept { \
414 return s.size(); \
415 } \
David Tolnay767e00d2020-12-21 17:12:27 -0800416 CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
417 std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
418 return &(*s)[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700419 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800420 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700421 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
422 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700423 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800424 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700425 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700426 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700427 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700428 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700429 const std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800430 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700431 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700432 return ptr.get(); \
433 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700434 std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800435 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700436 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700437 return ptr.release(); \
438 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800439 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700440 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700441 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700442 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700443
David Tolnay6787be62020-04-25 11:01:02 -0700444#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay0f0162f2020-11-16 23:43:37 -0800445 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700446 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800447 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700448 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800449 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700450 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800451 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
David Tolnaydc62d712020-12-11 13:51:53 -0800452 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800453 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700454 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800455 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800456 rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800457 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
David Tolnaye1df7dd2020-12-27 02:51:51 -0800458 std::size_t len) noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700459
460#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
461 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700462 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800463 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700464 } \
465 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700466 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800467 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700468 } \
469 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800470 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800471 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700472 } \
473 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800474 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
David Tolnaydc62d712020-12-11 13:51:53 -0800475 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
476 } \
477 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700478 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800479 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700480 } \
481 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800482 void Vec<CXX_TYPE>::reserve_total(std::size_t cap) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800483 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, cap); \
David Tolnayfb6b73c2020-11-10 14:32:16 -0800484 } \
485 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800486 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800487 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
David Tolnay6787be62020-04-25 11:01:02 -0700488 }
489
David Tolnay5b163402020-12-10 19:26:02 -0800490#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
491 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
492 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
493 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
494 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
495 new (ptr) std::shared_ptr<CXX_TYPE>(); \
496 } \
497 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
498 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
499 CXX_TYPE *uninit = \
500 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
501 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
502 return uninit; \
503 } \
504 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
505 const std::shared_ptr<CXX_TYPE> &self, \
506 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
507 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
508 } \
509 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
510 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
511 return self.get(); \
512 } \
513 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
514 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
515 self->~shared_ptr(); \
David Tolnay215e77f2020-12-28 17:09:48 -0800516 } \
517 static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
518 static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
519 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
520 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
521 new (ptr) std::weak_ptr<CXX_TYPE>(); \
522 } \
523 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
524 const std::weak_ptr<CXX_TYPE> &self, \
525 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
526 new (ptr) std::weak_ptr<CXX_TYPE>(self); \
527 } \
David Tolnay85b6bc42020-12-28 17:47:51 -0800528 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
529 const std::shared_ptr<CXX_TYPE> &shared, \
530 std::weak_ptr<CXX_TYPE> *weak) noexcept { \
531 new (weak) std::weak_ptr<CXX_TYPE>(shared); \
532 } \
David Tolnay7a487852020-12-28 18:02:25 -0800533 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
534 const std::weak_ptr<CXX_TYPE> &weak, \
535 std::shared_ptr<CXX_TYPE> *shared) noexcept { \
536 new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
537 } \
David Tolnay215e77f2020-12-28 17:09:48 -0800538 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
539 const std::weak_ptr<CXX_TYPE> *self) noexcept { \
540 self->~weak_ptr(); \
David Tolnay5b163402020-12-10 19:26:02 -0800541 }
542
David Tolnay6787be62020-04-25 11:01:02 -0700543// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700544#define FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800545 MACRO(u8, std::uint8_t) \
546 MACRO(u16, std::uint16_t) \
547 MACRO(u32, std::uint32_t) \
548 MACRO(u64, std::uint64_t) \
549 MACRO(i8, std::int8_t) \
550 MACRO(i16, std::int16_t) \
551 MACRO(i32, std::int32_t) \
552 MACRO(i64, std::int64_t) \
David Tolnay6787be62020-04-25 11:01:02 -0700553 MACRO(f32, float) \
554 MACRO(f64, double)
555
David Tolnayf336b3b2020-04-30 08:45:54 -0700556#define FOR_EACH_STD_VECTOR(MACRO) \
557 FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800558 MACRO(usize, std::size_t) \
David Tolnay47e239d2020-08-28 00:32:04 -0700559 MACRO(isize, rust::isize) \
560 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700561
David Tolnayf336b3b2020-04-30 08:45:54 -0700562#define FOR_EACH_RUST_VEC(MACRO) \
563 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700564 MACRO(bool, bool) \
David Tolnay93e71d02020-11-25 20:16:52 -0800565 MACRO(char, char) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700566 MACRO(string, rust::String)
David Tolnayf336b3b2020-04-30 08:45:54 -0700567
David Tolnay5b163402020-12-10 19:26:02 -0800568#define FOR_EACH_SHARED_PTR(MACRO) \
569 FOR_EACH_NUMERIC(MACRO) \
David Tolnaycd1430c2020-12-28 17:17:14 -0800570 MACRO(bool, bool) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800571 MACRO(usize, std::size_t) \
David Tolnay5b163402020-12-10 19:26:02 -0800572 MACRO(isize, rust::isize) \
573 MACRO(string, std::string)
574
David Tolnay4e7e7c42020-04-24 14:48:07 -0700575extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700576FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
577FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay5b163402020-12-10 19:26:02 -0800578FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700579} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700580
David Tolnay1768d8f2020-04-25 18:15:11 -0700581namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -0800582inline namespace cxxbridge1 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700583FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay0f0162f2020-11-16 23:43:37 -0800584} // namespace cxxbridge1
David Tolnay1768d8f2020-04-25 18:15:11 -0700585} // namespace rust