blob: 0f87bfe9ff83269d831970234bc354e7e82b8290 [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 Tolnay1202de52021-01-02 01:26:33 -080042void cxxbridge1$str$new(rust::Str *self) noexcept;
43void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
44bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
45 std::size_t len) noexcept;
46const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
47std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
David Tolnay9bffb932021-01-02 02:15:21 -080048
49// rust::Slice
50void cxxbridge1$slice$new(void *self, const void *ptr,
51 std::size_t len) noexcept;
52void *cxxbridge1$slice$ptr(const void *self) noexcept;
53std::size_t cxxbridge1$slice$len(const void *self) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040054} // extern "C"
55
David Tolnay750755e2020-03-01 13:04:08 -080056namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080057inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040058
David Tolnay521d99d2020-08-26 20:45:40 -070059template <typename Exception>
60void panic [[noreturn]] (const char *msg) {
61#if defined(RUST_CXX_NO_EXCEPTIONS)
62 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
63 std::terminate();
64#else
65 throw Exception(msg);
66#endif
67}
68
David Tolnayb10c4bc2020-08-26 21:55:29 -070069template void panic<std::out_of_range>[[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070070
David Tolnay0f0162f2020-11-16 23:43:37 -080071String::String() noexcept { cxxbridge1$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040072
David Tolnay56082162020-03-01 12:57:33 -080073String::String(const String &other) noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -080074 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040075}
76
David Tolnay15671862020-11-23 18:13:56 -080077String::String(String &&other) noexcept : repr(other.repr) {
David Tolnay0f0162f2020-11-16 23:43:37 -080078 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040079}
80
David Tolnay0f0162f2020-11-16 23:43:37 -080081String::~String() noexcept { cxxbridge1$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040082
David Tolnaybe3cbf72020-12-12 22:12:07 -080083static void initString(String *self, const char *s, std::size_t len) {
David Tolnay0f0162f2020-11-16 23:43:37 -080084 if (!cxxbridge1$string$from(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070085 panic<std::invalid_argument>("data for rust::String is not utf-8");
86 }
87}
David Tolnay7db73692019-10-20 14:51:12 -040088
David Tolnay032d8532020-10-30 20:47:31 -070089String::String(const std::string &s) { initString(this, s.data(), s.length()); }
90
David Tolnay54b13222020-10-30 20:58:32 -070091String::String(const char *s) {
92 assert(s != nullptr);
93 initString(this, s, std::strlen(s));
94}
David Tolnayc2bbd952020-07-29 18:15:26 -070095
David Tolnaybe3cbf72020-12-12 22:12:07 -080096String::String(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -070097 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -070098 initString(this,
99 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
100 len);
David Tolnay7db73692019-10-20 14:51:12 -0400101}
102
David Tolnay63bec402021-02-11 23:18:04 -0800103String &String::operator=(const String &other) & noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400104 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800105 cxxbridge1$string$drop(this);
106 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -0400107 }
108 return *this;
109}
110
David Tolnay63bec402021-02-11 23:18:04 -0800111String &String::operator=(String &&other) & noexcept {
David Tolnay7bc397c2021-02-11 23:07:58 -0800112 cxxbridge1$string$drop(this);
113 this->repr = other.repr;
114 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -0400115 return *this;
116}
117
David Tolnayd9c4ac92020-03-01 20:33:58 -0800118String::operator std::string() const {
119 return std::string(this->data(), this->size());
120}
121
David Tolnay56082162020-03-01 12:57:33 -0800122const char *String::data() const noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -0800123 return cxxbridge1$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -0400124}
125
David Tolnaybe3cbf72020-12-12 22:12:07 -0800126std::size_t String::size() const noexcept {
127 return cxxbridge1$string$len(this);
128}
David Tolnay7db73692019-10-20 14:51:12 -0400129
David Tolnaybe3cbf72020-12-12 22:12:07 -0800130std::size_t String::length() const noexcept {
131 return cxxbridge1$string$len(this);
132}
David Tolnay7db73692019-10-20 14:51:12 -0400133
David Tolnaycca2e612020-12-18 12:48:22 -0800134const char *String::c_str() noexcept {
135 auto len = this->length();
136 cxxbridge1$string$reserve_total(this, len + 1);
137 auto ptr = this->data();
138 const_cast<char *>(ptr)[len] = '\0';
139 return ptr;
140}
141
David Tolnayff7f5fb2020-11-25 20:50:32 -0800142String::iterator String::begin() noexcept {
143 return const_cast<char *>(this->data());
144}
145
146String::iterator String::end() noexcept {
147 return const_cast<char *>(this->data()) + this->size();
148}
149
150String::const_iterator String::begin() const noexcept { return this->cbegin(); }
151
152String::const_iterator String::end() const noexcept { return this->cend(); }
153
154String::const_iterator String::cbegin() const noexcept { return this->data(); }
155
156String::const_iterator String::cend() const noexcept {
157 return this->data() + this->size();
158}
159
David Tolnayff86dce2020-11-29 19:45:13 -0800160bool String::operator==(const String &rhs) const noexcept {
161 return rust::Str(*this) == rust::Str(rhs);
162}
163
164bool String::operator!=(const String &rhs) const noexcept {
165 return rust::Str(*this) != rust::Str(rhs);
166}
167
168bool String::operator<(const String &rhs) const noexcept {
169 return rust::Str(*this) < rust::Str(rhs);
170}
171
172bool String::operator<=(const String &rhs) const noexcept {
173 return rust::Str(*this) <= rust::Str(rhs);
174}
175
176bool String::operator>(const String &rhs) const noexcept {
177 return rust::Str(*this) > rust::Str(rhs);
178}
179
180bool String::operator>=(const String &rhs) const noexcept {
181 return rust::Str(*this) >= rust::Str(rhs);
182}
183
David Tolnayfec17152021-01-02 12:51:29 -0800184void String::swap(String &rhs) noexcept {
185 using std::swap;
186 swap(this->repr, rhs.repr);
187}
188
David Tolnayd1e2efc2020-03-03 22:25:43 -0800189String::String(unsafe_bitcopy_t, const String &bits) noexcept
190 : repr(bits.repr) {}
191
David Tolnay56082162020-03-01 12:57:33 -0800192std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400193 os.write(s.data(), s.size());
194 return os;
195}
196
David Tolnay1202de52021-01-02 01:26:33 -0800197Str::Str() noexcept { cxxbridge1$str$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400198
David Tolnay1202de52021-01-02 01:26:33 -0800199Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
David Tolnay828e5132020-11-29 20:40:40 -0800200
David Tolnay1202de52021-01-02 01:26:33 -0800201static void initStr(Str *self, const char *ptr, std::size_t len) {
202 if (!cxxbridge1$str$from(self, ptr, len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700203 panic<std::invalid_argument>("data for rust::Str is not utf-8");
204 }
205}
David Tolnay7db73692019-10-20 14:51:12 -0400206
David Tolnay1202de52021-01-02 01:26:33 -0800207Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
David Tolnay894c5e42020-07-29 18:20:00 -0700208
David Tolnay1202de52021-01-02 01:26:33 -0800209Str::Str(const char *s) {
David Tolnay54b13222020-10-30 20:58:32 -0700210 assert(s != nullptr);
David Tolnay1202de52021-01-02 01:26:33 -0800211 initStr(this, s, std::strlen(s));
David Tolnay54b13222020-10-30 20:58:32 -0700212}
David Tolnay032d8532020-10-30 20:47:31 -0700213
David Tolnay1202de52021-01-02 01:26:33 -0800214Str::Str(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -0700215 assert(s != nullptr || len == 0);
David Tolnay1202de52021-01-02 01:26:33 -0800216 initStr(this,
217 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
218 len);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800219}
David Tolnay7db73692019-10-20 14:51:12 -0400220
David Tolnay09dbe752020-03-01 13:00:40 -0800221Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400222 return std::string(this->data(), this->size());
223}
224
David Tolnay1202de52021-01-02 01:26:33 -0800225const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
226
227std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
228
229std::size_t Str::length() const noexcept { return this->size(); }
230
David Tolnayff7f5fb2020-11-25 20:50:32 -0800231Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
232
233Str::const_iterator Str::end() const noexcept { return this->cend(); }
234
David Tolnay1202de52021-01-02 01:26:33 -0800235Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
David Tolnayff7f5fb2020-11-25 20:50:32 -0800236
David Tolnay1202de52021-01-02 01:26:33 -0800237Str::const_iterator Str::cend() const noexcept {
238 return this->data() + this->size();
239}
David Tolnayff7f5fb2020-11-25 20:50:32 -0800240
David Tolnayff86dce2020-11-29 19:45:13 -0800241bool Str::operator==(const Str &rhs) const noexcept {
David Tolnay1202de52021-01-02 01:26:33 -0800242 return this->size() == rhs.size() &&
David Tolnayff86dce2020-11-29 19:45:13 -0800243 std::equal(this->begin(), this->end(), rhs.begin());
244}
245
246bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
247
248bool Str::operator<(const Str &rhs) const noexcept {
249 return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
250 rhs.end());
251}
252
253bool Str::operator<=(const Str &rhs) const noexcept {
254 // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
255 // without Undefined Behavior on C++11 if rhs is shorter than *this.
256 const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
257 rend = rhs.end();
258 while (liter != lend && riter != rend && *liter == *riter) {
259 ++liter, ++riter;
260 }
261 if (liter == lend) {
262 return true; // equal or *this is a prefix of rhs
263 } else if (riter == rend) {
264 return false; // rhs is a prefix of *this
265 } else {
266 return *liter <= *riter;
267 }
268}
269
270bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
271
272bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
273
David Tolnayba750b62021-01-02 16:05:48 -0800274void Str::swap(Str &rhs) noexcept {
275 using std::swap;
276 swap(this->repr, rhs.repr);
277}
David Tolnay0413ee22021-01-02 13:55:16 -0800278
David Tolnay09dbe752020-03-01 13:00:40 -0800279std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400280 os.write(s.data(), s.size());
281 return os;
282}
283
David Tolnay9bffb932021-01-02 02:15:21 -0800284void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
285 cxxbridge1$slice$new(self, ptr, len);
286}
287
288void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
289
290std::size_t sliceLen(const void *self) noexcept {
291 return cxxbridge1$slice$len(self);
292}
293
David Tolnay03c43f52020-12-12 21:07:17 -0800294// Rust specifies that usize is ABI compatible with C's uintptr_t.
295// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
296// However there is no direct Rust equivalent for size_t. C does not guarantee
297// that size_t and uintptr_t are compatible. In practice though, on all
298// platforms supported by Rust, they are identical for ABI purposes. See the
299// libc crate which unconditionally defines libc::size_t = usize. We expect the
300// same here and these assertions are just here to explicitly document that.
301// *Note that no assumption is made about C++ name mangling of signatures
302// containing these types, not here nor anywhere in CXX.*
David Tolnaybe3cbf72020-12-12 22:12:07 -0800303static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
304 "unsupported size_t size");
305static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800306 "unsupported size_t alignment");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800307static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800308 "unsupported ssize_t size");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800309static_assert(alignof(rust::isize) == alignof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800310 "unsupported ssize_t alignment");
311
David Tolnay9ed15c62020-10-31 18:02:03 -0700312static_assert(std::is_trivially_copy_constructible<Str>::value,
313 "trivial Str(const Str &)");
314static_assert(std::is_trivially_copy_assignable<Str>::value,
315 "trivial operator=(const Str &)");
316static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
317
David Tolnay9578cf12020-11-25 14:36:46 -0800318static_assert(
David Tolnaybe3cbf72020-12-12 22:12:07 -0800319 std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
320 "trivial Slice(const Slice &)");
321static_assert(
322 std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
323 "trivial Slice(Slice &&)");
324static_assert(
325 std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
326 "trivial Slice::operator=(const Slice &) for const slices");
327static_assert(
328 std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
329 "trivial Slice::operator=(Slice &&)");
330static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
331 "trivial ~Slice()");
332
333static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
334 "trivial Slice(const Slice &)");
335static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
336 "trivial Slice(Slice &&)");
337static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
338 "delete Slice::operator=(const Slice &) for mut slices");
339static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
340 "trivial Slice::operator=(Slice &&)");
341static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
342 "trivial ~Slice()");
343
344static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
345 Vec<const std::uint8_t>::iterator>::value,
346 "Vec<T>::const_iterator == Vec<const T>::iterator");
347static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
348 Vec<const std::uint8_t>::iterator>::value,
349 "Vec<const T>::const_iterator == Vec<const T>::iterator");
350static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
351 Vec<std::uint8_t>::iterator>::value,
352 "Vec<T>::const_iterator != Vec<T>::iterator");
David Tolnay9578cf12020-11-25 14:36:46 -0800353
David Tolnay4ddae802021-01-02 16:47:33 -0800354static const char *errorCopy(const char *ptr, std::size_t len) {
355 char *copy = new char[len];
356 std::memcpy(copy, ptr, len);
357 return copy;
358}
359
David Tolnay1e548172020-03-16 13:37:09 -0700360extern "C" {
David Tolnaydc2d4c32021-01-02 16:13:27 -0800361const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
David Tolnay4ddae802021-01-02 16:47:33 -0800362 return errorCopy(ptr, len);
David Tolnay1e548172020-03-16 13:37:09 -0700363}
364} // extern "C"
365
David Tolnayd5712ee2020-10-31 17:10:00 -0700366Error::Error(const Error &other)
David Tolnay4ddae802021-01-02 16:47:33 -0800367 : std::exception(other),
368 msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
David Tolnay23c23192020-10-31 17:11:48 -0700369 len(other.len) {}
David Tolnay1e548172020-03-16 13:37:09 -0700370
David Tolnay23c23192020-10-31 17:11:48 -0700371Error::Error(Error &&other) noexcept
372 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
David Tolnaya0c9bc72020-10-31 14:37:14 -0700373 other.msg = nullptr;
374 other.len = 0;
David Tolnay1e548172020-03-16 13:37:09 -0700375}
376
David Tolnaya0c9bc72020-10-31 14:37:14 -0700377Error::~Error() noexcept { delete[] this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700378
David Tolnay63bec402021-02-11 23:18:04 -0800379Error &Error::operator=(const Error &other) & {
David Tolnay7c6ac712020-10-31 17:22:28 -0700380 if (this != &other) {
381 std::exception::operator=(other);
382 delete[] this->msg;
383 this->msg = nullptr;
David Tolnay4ddae802021-01-02 16:47:33 -0800384 if (other.msg) {
385 this->msg = errorCopy(other.msg, other.len);
386 this->len = other.len;
387 }
David Tolnay7c6ac712020-10-31 17:22:28 -0700388 }
389 return *this;
390}
391
David Tolnay63bec402021-02-11 23:18:04 -0800392Error &Error::operator=(Error &&other) & noexcept {
David Tolnay7bc397c2021-02-11 23:07:58 -0800393 std::exception::operator=(std::move(other));
394 this->msg = other.msg;
395 this->len = other.len;
396 other.msg = nullptr;
397 other.len = 0;
David Tolnay15491062020-10-31 17:25:13 -0700398 return *this;
399}
400
David Tolnaya0c9bc72020-10-31 14:37:14 -0700401const char *Error::what() const noexcept { return this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700402
David Tolnay5b163402020-12-10 19:26:02 -0800403namespace {
404template <typename T>
405union MaybeUninit {
406 T value;
407 MaybeUninit() {}
408 ~MaybeUninit() {}
409};
410} // namespace
411
David Tolnay60f83592021-02-08 23:00:01 -0800412namespace detail {
413// On some platforms size_t is the same C++ type as one of the sized integer
414// types; on others it is a distinct type. Only in the latter case do we need to
415// define a specialized impl of rust::Vec<size_t>, because in the former case it
416// would collide with one of the other specializations.
417using usize_if_unique =
418 typename std::conditional<std::is_same<size_t, uint64_t>::value ||
419 std::is_same<size_t, uint32_t>::value,
420 struct usize_ignore, size_t>::type;
421using isize_if_unique =
422 typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
423 std::is_same<rust::isize, int32_t>::value,
424 struct isize_ignore, rust::isize>::type;
425} // namespace detail
426
David Tolnay0f0162f2020-11-16 23:43:37 -0800427} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -0800428} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400429
430extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800431void cxxbridge1$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400432 std::unique_ptr<std::string> *ptr) noexcept {
433 new (ptr) std::unique_ptr<std::string>();
434}
David Tolnay0f0162f2020-11-16 23:43:37 -0800435void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
436 std::string *raw) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400437 new (ptr) std::unique_ptr<std::string>(raw);
438}
David Tolnay0f0162f2020-11-16 23:43:37 -0800439const std::string *cxxbridge1$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400440 const std::unique_ptr<std::string> &ptr) noexcept {
441 return ptr.get();
442}
David Tolnay0f0162f2020-11-16 23:43:37 -0800443std::string *cxxbridge1$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400444 std::unique_ptr<std::string> &ptr) noexcept {
445 return ptr.release();
446}
David Tolnay0f0162f2020-11-16 23:43:37 -0800447void cxxbridge1$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400448 std::unique_ptr<std::string> *ptr) noexcept {
449 ptr->~unique_ptr();
450}
451} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700452
David Tolnay06677b32020-11-23 18:05:45 -0800453namespace {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800454const std::size_t kMaxExpectedWordsInString = 8;
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800455static_assert(alignof(std::string) <= alignof(void *),
456 "unexpectedly large std::string alignment");
David Tolnay06677b32020-11-23 18:05:45 -0800457static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800458 "unexpectedly large std::string size");
David Tolnayc26de542020-11-23 18:18:19 -0800459} // namespace
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800460
David Tolnay37dd7e12020-04-25 12:51:59 -0700461#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800462 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700463 const std::vector<CXX_TYPE> &s) noexcept { \
464 return s.size(); \
465 } \
David Tolnay767e00d2020-12-21 17:12:27 -0800466 CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
467 std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
468 return &(*s)[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700469 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800470 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700471 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
472 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700473 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800474 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700475 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700476 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700477 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700478 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700479 const std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800480 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700481 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700482 return ptr.get(); \
483 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700484 std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800485 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700486 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700487 return ptr.release(); \
488 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800489 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700490 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700491 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700492 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700493
David Tolnay6787be62020-04-25 11:01:02 -0700494#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay0f0162f2020-11-16 23:43:37 -0800495 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700496 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800497 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700498 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800499 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700500 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800501 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
David Tolnaydc62d712020-12-11 13:51:53 -0800502 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800503 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700504 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800505 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800506 rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800507 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
David Tolnaye1df7dd2020-12-27 02:51:51 -0800508 std::size_t len) noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700509
510#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
511 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700512 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800513 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700514 } \
515 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700516 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800517 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700518 } \
519 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800520 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800521 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700522 } \
523 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800524 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
David Tolnaydc62d712020-12-11 13:51:53 -0800525 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
526 } \
527 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700528 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800529 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700530 } \
531 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800532 void Vec<CXX_TYPE>::reserve_total(std::size_t cap) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800533 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, cap); \
David Tolnayfb6b73c2020-11-10 14:32:16 -0800534 } \
535 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800536 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800537 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
David Tolnay6787be62020-04-25 11:01:02 -0700538 }
539
David Tolnay5b163402020-12-10 19:26:02 -0800540#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
541 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
542 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
543 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
544 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
545 new (ptr) std::shared_ptr<CXX_TYPE>(); \
546 } \
547 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
548 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
549 CXX_TYPE *uninit = \
550 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
551 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
552 return uninit; \
553 } \
554 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
555 const std::shared_ptr<CXX_TYPE> &self, \
556 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
557 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
558 } \
559 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
560 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
561 return self.get(); \
562 } \
563 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
564 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
565 self->~shared_ptr(); \
David Tolnay215e77f2020-12-28 17:09:48 -0800566 } \
567 static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
568 static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
569 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
570 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
571 new (ptr) std::weak_ptr<CXX_TYPE>(); \
572 } \
573 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
574 const std::weak_ptr<CXX_TYPE> &self, \
575 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
576 new (ptr) std::weak_ptr<CXX_TYPE>(self); \
577 } \
David Tolnay85b6bc42020-12-28 17:47:51 -0800578 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
579 const std::shared_ptr<CXX_TYPE> &shared, \
580 std::weak_ptr<CXX_TYPE> *weak) noexcept { \
581 new (weak) std::weak_ptr<CXX_TYPE>(shared); \
582 } \
David Tolnay7a487852020-12-28 18:02:25 -0800583 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
584 const std::weak_ptr<CXX_TYPE> &weak, \
585 std::shared_ptr<CXX_TYPE> *shared) noexcept { \
586 new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
587 } \
David Tolnay215e77f2020-12-28 17:09:48 -0800588 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
589 const std::weak_ptr<CXX_TYPE> *self) noexcept { \
590 self->~weak_ptr(); \
David Tolnay5b163402020-12-10 19:26:02 -0800591 }
592
David Tolnay6787be62020-04-25 11:01:02 -0700593// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700594#define FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800595 MACRO(u8, std::uint8_t) \
596 MACRO(u16, std::uint16_t) \
597 MACRO(u32, std::uint32_t) \
598 MACRO(u64, std::uint64_t) \
599 MACRO(i8, std::int8_t) \
600 MACRO(i16, std::int16_t) \
601 MACRO(i32, std::int32_t) \
602 MACRO(i64, std::int64_t) \
David Tolnay6787be62020-04-25 11:01:02 -0700603 MACRO(f32, float) \
604 MACRO(f64, double)
605
David Tolnayf336b3b2020-04-30 08:45:54 -0700606#define FOR_EACH_STD_VECTOR(MACRO) \
607 FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800608 MACRO(usize, std::size_t) \
David Tolnay47e239d2020-08-28 00:32:04 -0700609 MACRO(isize, rust::isize) \
610 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700611
David Tolnayf336b3b2020-04-30 08:45:54 -0700612#define FOR_EACH_RUST_VEC(MACRO) \
613 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700614 MACRO(bool, bool) \
David Tolnay93e71d02020-11-25 20:16:52 -0800615 MACRO(char, char) \
David Tolnay60f83592021-02-08 23:00:01 -0800616 MACRO(usize, rust::detail::usize_if_unique) \
617 MACRO(isize, rust::detail::isize_if_unique) \
David Tolnay2d1fcc22021-01-03 22:43:19 -0800618 MACRO(string, rust::String) \
619 MACRO(str, rust::Str)
David Tolnayf336b3b2020-04-30 08:45:54 -0700620
David Tolnay5b163402020-12-10 19:26:02 -0800621#define FOR_EACH_SHARED_PTR(MACRO) \
622 FOR_EACH_NUMERIC(MACRO) \
David Tolnaycd1430c2020-12-28 17:17:14 -0800623 MACRO(bool, bool) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800624 MACRO(usize, std::size_t) \
David Tolnay5b163402020-12-10 19:26:02 -0800625 MACRO(isize, rust::isize) \
626 MACRO(string, std::string)
627
David Tolnay4e7e7c42020-04-24 14:48:07 -0700628extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700629FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
630FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay5b163402020-12-10 19:26:02 -0800631FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700632} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700633
David Tolnay1768d8f2020-04-25 18:15:11 -0700634namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -0800635inline namespace cxxbridge1 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700636FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay0f0162f2020-11-16 23:43:37 -0800637} // namespace cxxbridge1
David Tolnay1768d8f2020-04-25 18:15:11 -0700638} // namespace rust