blob: 921b17db4dd765a583ccb3b5835d84fa524d6fc6 [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 Tolnayf2a14662021-08-12 13:47:46 -070025void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
26
David Tolnaybe3cbf72020-12-12 22:12:07 -080027void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
28 std::size_t len) noexcept {
David Tolnay90691f42020-11-14 20:01:46 -080029 s.append(reinterpret_cast<const char *>(ptr), len);
30}
31
David Tolnay750755e2020-03-01 13:04:08 -080032// rust::String
David Tolnay0f0162f2020-11-16 23:43:37 -080033void cxxbridge1$string$new(rust::String *self) noexcept;
34void cxxbridge1$string$clone(rust::String *self,
35 const rust::String &other) noexcept;
Gerhard de Clercq31a41022021-07-31 15:17:27 +020036bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr,
37 std::size_t len) noexcept;
38bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr,
39 std::size_t len) noexcept;
David Tolnay0f0162f2020-11-16 23:43:37 -080040void cxxbridge1$string$drop(rust::String *self) noexcept;
41const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
David Tolnaybe3cbf72020-12-12 22:12:07 -080042std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
David Tolnay185c2cb2021-08-27 11:47:52 -070043void cxxbridge1$string$reserve_additional(rust::String *self,
44 size_t additional) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040045
David Tolnay750755e2020-03-01 13:04:08 -080046// rust::Str
David Tolnay1202de52021-01-02 01:26:33 -080047void cxxbridge1$str$new(rust::Str *self) noexcept;
48void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
49bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
50 std::size_t len) noexcept;
51const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
52std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
David Tolnay9bffb932021-01-02 02:15:21 -080053
54// rust::Slice
55void cxxbridge1$slice$new(void *self, const void *ptr,
56 std::size_t len) noexcept;
57void *cxxbridge1$slice$ptr(const void *self) noexcept;
58std::size_t cxxbridge1$slice$len(const void *self) noexcept;
David Tolnay7db73692019-10-20 14:51:12 -040059} // extern "C"
60
David Tolnay750755e2020-03-01 13:04:08 -080061namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -080062inline namespace cxxbridge1 {
David Tolnay7db73692019-10-20 14:51:12 -040063
David Tolnay521d99d2020-08-26 20:45:40 -070064template <typename Exception>
65void panic [[noreturn]] (const char *msg) {
66#if defined(RUST_CXX_NO_EXCEPTIONS)
67 std::cerr << "Error: " << msg << ". Aborting." << std::endl;
68 std::terminate();
69#else
70 throw Exception(msg);
71#endif
72}
73
David Tolnayde01edf2021-03-22 15:00:15 -070074template void panic<std::out_of_range> [[noreturn]] (const char *msg);
David Tolnay521d99d2020-08-26 20:45:40 -070075
David Tolnay0f0162f2020-11-16 23:43:37 -080076String::String() noexcept { cxxbridge1$string$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -040077
David Tolnay56082162020-03-01 12:57:33 -080078String::String(const String &other) noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -080079 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -040080}
81
David Tolnay15671862020-11-23 18:13:56 -080082String::String(String &&other) noexcept : repr(other.repr) {
David Tolnay0f0162f2020-11-16 23:43:37 -080083 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -040084}
85
David Tolnay0f0162f2020-11-16 23:43:37 -080086String::~String() noexcept { cxxbridge1$string$drop(this); }
David Tolnay7db73692019-10-20 14:51:12 -040087
David Tolnaybe3cbf72020-12-12 22:12:07 -080088static void initString(String *self, const char *s, std::size_t len) {
Gerhard de Clercq31a41022021-07-31 15:17:27 +020089 if (!cxxbridge1$string$from_utf8(self, s, len)) {
David Tolnay8d323662020-10-30 19:32:26 -070090 panic<std::invalid_argument>("data for rust::String is not utf-8");
91 }
92}
David Tolnay7db73692019-10-20 14:51:12 -040093
Gerhard de Clercq31a41022021-07-31 15:17:27 +020094static void initString(String *self, const char16_t *s, std::size_t len) {
95 if (!cxxbridge1$string$from_utf16(self, s, len)) {
96 panic<std::invalid_argument>("data for rust::String is not utf-16");
97 }
98}
99
David Tolnay032d8532020-10-30 20:47:31 -0700100String::String(const std::string &s) { initString(this, s.data(), s.length()); }
101
David Tolnay54b13222020-10-30 20:58:32 -0700102String::String(const char *s) {
103 assert(s != nullptr);
104 initString(this, s, std::strlen(s));
105}
David Tolnayc2bbd952020-07-29 18:15:26 -0700106
David Tolnaybe3cbf72020-12-12 22:12:07 -0800107String::String(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -0700108 assert(s != nullptr || len == 0);
David Tolnay032d8532020-10-30 20:47:31 -0700109 initString(this,
110 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
111 len);
David Tolnay7db73692019-10-20 14:51:12 -0400112}
113
Gerhard de Clercq31a41022021-07-31 15:17:27 +0200114String::String(const char16_t *s) {
115 assert(s != nullptr);
116 initString(this, s, std::char_traits<char16_t>::length(s));
117}
118
119String::String(const char16_t *s, std::size_t len) {
120 assert(s != nullptr || len == 0);
121 initString(this,
122 s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2)
123 : s,
124 len);
125}
126
David Tolnay5d12f1d2021-03-22 14:58:38 -0700127String &String::operator=(const String &other) &noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400128 if (this != &other) {
David Tolnay0f0162f2020-11-16 23:43:37 -0800129 cxxbridge1$string$drop(this);
130 cxxbridge1$string$clone(this, other);
David Tolnay7db73692019-10-20 14:51:12 -0400131 }
132 return *this;
133}
134
David Tolnay5d12f1d2021-03-22 14:58:38 -0700135String &String::operator=(String &&other) &noexcept {
David Tolnay7bc397c2021-02-11 23:07:58 -0800136 cxxbridge1$string$drop(this);
137 this->repr = other.repr;
138 cxxbridge1$string$new(&other);
David Tolnay7db73692019-10-20 14:51:12 -0400139 return *this;
140}
141
David Tolnayd9c4ac92020-03-01 20:33:58 -0800142String::operator std::string() const {
143 return std::string(this->data(), this->size());
144}
145
David Tolnay56082162020-03-01 12:57:33 -0800146const char *String::data() const noexcept {
David Tolnay0f0162f2020-11-16 23:43:37 -0800147 return cxxbridge1$string$ptr(this);
David Tolnay7db73692019-10-20 14:51:12 -0400148}
149
David Tolnaybe3cbf72020-12-12 22:12:07 -0800150std::size_t String::size() const noexcept {
151 return cxxbridge1$string$len(this);
152}
David Tolnay7db73692019-10-20 14:51:12 -0400153
David Tolnaybe3cbf72020-12-12 22:12:07 -0800154std::size_t String::length() const noexcept {
155 return cxxbridge1$string$len(this);
156}
David Tolnay7db73692019-10-20 14:51:12 -0400157
David Tolnay99f79c02021-04-28 00:29:55 -0700158bool String::empty() const noexcept { return this->size() == 0; }
159
David Tolnaycca2e612020-12-18 12:48:22 -0800160const char *String::c_str() noexcept {
161 auto len = this->length();
David Tolnay185c2cb2021-08-27 11:47:52 -0700162 cxxbridge1$string$reserve_additional(this, 1);
David Tolnaycca2e612020-12-18 12:48:22 -0800163 auto ptr = this->data();
164 const_cast<char *>(ptr)[len] = '\0';
165 return ptr;
166}
167
David Tolnayff7f5fb2020-11-25 20:50:32 -0800168String::iterator String::begin() noexcept {
169 return const_cast<char *>(this->data());
170}
171
172String::iterator String::end() noexcept {
173 return const_cast<char *>(this->data()) + this->size();
174}
175
176String::const_iterator String::begin() const noexcept { return this->cbegin(); }
177
178String::const_iterator String::end() const noexcept { return this->cend(); }
179
180String::const_iterator String::cbegin() const noexcept { return this->data(); }
181
182String::const_iterator String::cend() const noexcept {
183 return this->data() + this->size();
184}
185
David Tolnayff86dce2020-11-29 19:45:13 -0800186bool String::operator==(const String &rhs) const noexcept {
187 return rust::Str(*this) == rust::Str(rhs);
188}
189
190bool String::operator!=(const String &rhs) const noexcept {
191 return rust::Str(*this) != rust::Str(rhs);
192}
193
194bool String::operator<(const String &rhs) const noexcept {
195 return rust::Str(*this) < rust::Str(rhs);
196}
197
198bool String::operator<=(const String &rhs) const noexcept {
199 return rust::Str(*this) <= rust::Str(rhs);
200}
201
202bool String::operator>(const String &rhs) const noexcept {
203 return rust::Str(*this) > rust::Str(rhs);
204}
205
206bool String::operator>=(const String &rhs) const noexcept {
207 return rust::Str(*this) >= rust::Str(rhs);
208}
209
David Tolnayfec17152021-01-02 12:51:29 -0800210void String::swap(String &rhs) noexcept {
211 using std::swap;
212 swap(this->repr, rhs.repr);
213}
214
David Tolnayd1e2efc2020-03-03 22:25:43 -0800215String::String(unsafe_bitcopy_t, const String &bits) noexcept
216 : repr(bits.repr) {}
217
David Tolnay56082162020-03-01 12:57:33 -0800218std::ostream &operator<<(std::ostream &os, const String &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400219 os.write(s.data(), s.size());
220 return os;
221}
222
David Tolnay1202de52021-01-02 01:26:33 -0800223Str::Str() noexcept { cxxbridge1$str$new(this); }
David Tolnay7db73692019-10-20 14:51:12 -0400224
David Tolnay1202de52021-01-02 01:26:33 -0800225Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
David Tolnay828e5132020-11-29 20:40:40 -0800226
David Tolnay1202de52021-01-02 01:26:33 -0800227static void initStr(Str *self, const char *ptr, std::size_t len) {
228 if (!cxxbridge1$str$from(self, ptr, len)) {
David Tolnay8d323662020-10-30 19:32:26 -0700229 panic<std::invalid_argument>("data for rust::Str is not utf-8");
230 }
231}
David Tolnay7db73692019-10-20 14:51:12 -0400232
David Tolnay1202de52021-01-02 01:26:33 -0800233Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
David Tolnay894c5e42020-07-29 18:20:00 -0700234
David Tolnay1202de52021-01-02 01:26:33 -0800235Str::Str(const char *s) {
David Tolnay54b13222020-10-30 20:58:32 -0700236 assert(s != nullptr);
David Tolnay1202de52021-01-02 01:26:33 -0800237 initStr(this, s, std::strlen(s));
David Tolnay54b13222020-10-30 20:58:32 -0700238}
David Tolnay032d8532020-10-30 20:47:31 -0700239
David Tolnay1202de52021-01-02 01:26:33 -0800240Str::Str(const char *s, std::size_t len) {
David Tolnay54b13222020-10-30 20:58:32 -0700241 assert(s != nullptr || len == 0);
David Tolnay1202de52021-01-02 01:26:33 -0800242 initStr(this,
243 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
244 len);
David Tolnayd9c4ac92020-03-01 20:33:58 -0800245}
David Tolnay7db73692019-10-20 14:51:12 -0400246
David Tolnay09dbe752020-03-01 13:00:40 -0800247Str::operator std::string() const {
David Tolnay7db73692019-10-20 14:51:12 -0400248 return std::string(this->data(), this->size());
249}
250
David Tolnay1202de52021-01-02 01:26:33 -0800251const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
252
253std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
254
255std::size_t Str::length() const noexcept { return this->size(); }
256
David Tolnay99f79c02021-04-28 00:29:55 -0700257bool Str::empty() const noexcept { return this->size() == 0; }
258
David Tolnayff7f5fb2020-11-25 20:50:32 -0800259Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
260
261Str::const_iterator Str::end() const noexcept { return this->cend(); }
262
David Tolnay1202de52021-01-02 01:26:33 -0800263Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
David Tolnayff7f5fb2020-11-25 20:50:32 -0800264
David Tolnay1202de52021-01-02 01:26:33 -0800265Str::const_iterator Str::cend() const noexcept {
266 return this->data() + this->size();
267}
David Tolnayff7f5fb2020-11-25 20:50:32 -0800268
David Tolnayff86dce2020-11-29 19:45:13 -0800269bool Str::operator==(const Str &rhs) const noexcept {
David Tolnay1202de52021-01-02 01:26:33 -0800270 return this->size() == rhs.size() &&
David Tolnayff86dce2020-11-29 19:45:13 -0800271 std::equal(this->begin(), this->end(), rhs.begin());
272}
273
274bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
275
276bool Str::operator<(const Str &rhs) const noexcept {
277 return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
278 rhs.end());
279}
280
281bool Str::operator<=(const Str &rhs) const noexcept {
282 // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
283 // without Undefined Behavior on C++11 if rhs is shorter than *this.
284 const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
285 rend = rhs.end();
286 while (liter != lend && riter != rend && *liter == *riter) {
287 ++liter, ++riter;
288 }
289 if (liter == lend) {
290 return true; // equal or *this is a prefix of rhs
291 } else if (riter == rend) {
292 return false; // rhs is a prefix of *this
293 } else {
294 return *liter <= *riter;
295 }
296}
297
298bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
299
300bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
301
David Tolnayba750b62021-01-02 16:05:48 -0800302void Str::swap(Str &rhs) noexcept {
303 using std::swap;
304 swap(this->repr, rhs.repr);
305}
David Tolnay0413ee22021-01-02 13:55:16 -0800306
David Tolnay09dbe752020-03-01 13:00:40 -0800307std::ostream &operator<<(std::ostream &os, const Str &s) {
David Tolnay7db73692019-10-20 14:51:12 -0400308 os.write(s.data(), s.size());
309 return os;
310}
311
David Tolnay9bffb932021-01-02 02:15:21 -0800312void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
313 cxxbridge1$slice$new(self, ptr, len);
314}
315
316void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
317
318std::size_t sliceLen(const void *self) noexcept {
319 return cxxbridge1$slice$len(self);
320}
321
David Tolnay03c43f52020-12-12 21:07:17 -0800322// Rust specifies that usize is ABI compatible with C's uintptr_t.
323// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
324// However there is no direct Rust equivalent for size_t. C does not guarantee
325// that size_t and uintptr_t are compatible. In practice though, on all
326// platforms supported by Rust, they are identical for ABI purposes. See the
327// libc crate which unconditionally defines libc::size_t = usize. We expect the
328// same here and these assertions are just here to explicitly document that.
329// *Note that no assumption is made about C++ name mangling of signatures
330// containing these types, not here nor anywhere in CXX.*
David Tolnaybe3cbf72020-12-12 22:12:07 -0800331static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
332 "unsupported size_t size");
333static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800334 "unsupported size_t alignment");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800335static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800336 "unsupported ssize_t size");
David Tolnaybe3cbf72020-12-12 22:12:07 -0800337static_assert(alignof(rust::isize) == alignof(std::intptr_t),
David Tolnay03c43f52020-12-12 21:07:17 -0800338 "unsupported ssize_t alignment");
339
David Tolnay9ed15c62020-10-31 18:02:03 -0700340static_assert(std::is_trivially_copy_constructible<Str>::value,
341 "trivial Str(const Str &)");
342static_assert(std::is_trivially_copy_assignable<Str>::value,
343 "trivial operator=(const Str &)");
344static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
345
David Tolnay9578cf12020-11-25 14:36:46 -0800346static_assert(
David Tolnaybe3cbf72020-12-12 22:12:07 -0800347 std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
348 "trivial Slice(const Slice &)");
349static_assert(
350 std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
351 "trivial Slice(Slice &&)");
352static_assert(
353 std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
354 "trivial Slice::operator=(const Slice &) for const slices");
355static_assert(
356 std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
357 "trivial Slice::operator=(Slice &&)");
358static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
359 "trivial ~Slice()");
360
361static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
362 "trivial Slice(const Slice &)");
363static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
364 "trivial Slice(Slice &&)");
365static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
366 "delete Slice::operator=(const Slice &) for mut slices");
367static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
368 "trivial Slice::operator=(Slice &&)");
369static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
370 "trivial ~Slice()");
371
372static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
373 Vec<const std::uint8_t>::iterator>::value,
374 "Vec<T>::const_iterator == Vec<const T>::iterator");
375static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
376 Vec<const std::uint8_t>::iterator>::value,
377 "Vec<const T>::const_iterator == Vec<const T>::iterator");
378static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
379 Vec<std::uint8_t>::iterator>::value,
380 "Vec<T>::const_iterator != Vec<T>::iterator");
David Tolnay9578cf12020-11-25 14:36:46 -0800381
David Tolnay4ddae802021-01-02 16:47:33 -0800382static const char *errorCopy(const char *ptr, std::size_t len) {
383 char *copy = new char[len];
384 std::memcpy(copy, ptr, len);
385 return copy;
386}
387
David Tolnay1e548172020-03-16 13:37:09 -0700388extern "C" {
David Tolnaydc2d4c32021-01-02 16:13:27 -0800389const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
David Tolnay4ddae802021-01-02 16:47:33 -0800390 return errorCopy(ptr, len);
David Tolnay1e548172020-03-16 13:37:09 -0700391}
392} // extern "C"
393
David Tolnayd5712ee2020-10-31 17:10:00 -0700394Error::Error(const Error &other)
David Tolnay4ddae802021-01-02 16:47:33 -0800395 : std::exception(other),
396 msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
David Tolnay23c23192020-10-31 17:11:48 -0700397 len(other.len) {}
David Tolnay1e548172020-03-16 13:37:09 -0700398
David Tolnay23c23192020-10-31 17:11:48 -0700399Error::Error(Error &&other) noexcept
400 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
David Tolnaya0c9bc72020-10-31 14:37:14 -0700401 other.msg = nullptr;
402 other.len = 0;
David Tolnay1e548172020-03-16 13:37:09 -0700403}
404
David Tolnaya0c9bc72020-10-31 14:37:14 -0700405Error::~Error() noexcept { delete[] this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700406
David Tolnay63bec402021-02-11 23:18:04 -0800407Error &Error::operator=(const Error &other) & {
David Tolnay7c6ac712020-10-31 17:22:28 -0700408 if (this != &other) {
409 std::exception::operator=(other);
410 delete[] this->msg;
411 this->msg = nullptr;
David Tolnay4ddae802021-01-02 16:47:33 -0800412 if (other.msg) {
413 this->msg = errorCopy(other.msg, other.len);
414 this->len = other.len;
415 }
David Tolnay7c6ac712020-10-31 17:22:28 -0700416 }
417 return *this;
418}
419
David Tolnay5d12f1d2021-03-22 14:58:38 -0700420Error &Error::operator=(Error &&other) &noexcept {
David Tolnay7bc397c2021-02-11 23:07:58 -0800421 std::exception::operator=(std::move(other));
422 this->msg = other.msg;
423 this->len = other.len;
424 other.msg = nullptr;
425 other.len = 0;
David Tolnay15491062020-10-31 17:25:13 -0700426 return *this;
427}
428
David Tolnaya0c9bc72020-10-31 14:37:14 -0700429const char *Error::what() const noexcept { return this->msg; }
David Tolnay1e548172020-03-16 13:37:09 -0700430
David Tolnay5b163402020-12-10 19:26:02 -0800431namespace {
432template <typename T>
433union MaybeUninit {
434 T value;
435 MaybeUninit() {}
436 ~MaybeUninit() {}
437};
438} // namespace
439
David Tolnay60f83592021-02-08 23:00:01 -0800440namespace detail {
441// On some platforms size_t is the same C++ type as one of the sized integer
442// types; on others it is a distinct type. Only in the latter case do we need to
443// define a specialized impl of rust::Vec<size_t>, because in the former case it
444// would collide with one of the other specializations.
445using usize_if_unique =
446 typename std::conditional<std::is_same<size_t, uint64_t>::value ||
447 std::is_same<size_t, uint32_t>::value,
448 struct usize_ignore, size_t>::type;
449using isize_if_unique =
450 typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
451 std::is_same<rust::isize, int32_t>::value,
452 struct isize_ignore, rust::isize>::type;
453} // namespace detail
454
David Tolnay0f0162f2020-11-16 23:43:37 -0800455} // namespace cxxbridge1
David Tolnay750755e2020-03-01 13:04:08 -0800456} // namespace rust
David Tolnay7db73692019-10-20 14:51:12 -0400457
David Tolnayfc26d6d2021-04-15 21:18:45 -0700458namespace {
459template <typename T>
460void destroy(T *ptr) {
461 ptr->~T();
462}
463} // namespace
464
David Tolnay7db73692019-10-20 14:51:12 -0400465extern "C" {
David Tolnay0f0162f2020-11-16 23:43:37 -0800466void cxxbridge1$unique_ptr$std$string$null(
David Tolnay7db73692019-10-20 14:51:12 -0400467 std::unique_ptr<std::string> *ptr) noexcept {
468 new (ptr) std::unique_ptr<std::string>();
469}
David Tolnay0f0162f2020-11-16 23:43:37 -0800470void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
471 std::string *raw) noexcept {
David Tolnay7db73692019-10-20 14:51:12 -0400472 new (ptr) std::unique_ptr<std::string>(raw);
473}
David Tolnay0f0162f2020-11-16 23:43:37 -0800474const std::string *cxxbridge1$unique_ptr$std$string$get(
David Tolnay7db73692019-10-20 14:51:12 -0400475 const std::unique_ptr<std::string> &ptr) noexcept {
476 return ptr.get();
477}
David Tolnay0f0162f2020-11-16 23:43:37 -0800478std::string *cxxbridge1$unique_ptr$std$string$release(
David Tolnay7db73692019-10-20 14:51:12 -0400479 std::unique_ptr<std::string> &ptr) noexcept {
480 return ptr.release();
481}
David Tolnay0f0162f2020-11-16 23:43:37 -0800482void cxxbridge1$unique_ptr$std$string$drop(
David Tolnay7db73692019-10-20 14:51:12 -0400483 std::unique_ptr<std::string> *ptr) noexcept {
484 ptr->~unique_ptr();
485}
486} // extern "C"
Myron Ahneba35cf2020-02-05 19:41:51 +0700487
David Tolnay06677b32020-11-23 18:05:45 -0800488namespace {
David Tolnaybe3cbf72020-12-12 22:12:07 -0800489const std::size_t kMaxExpectedWordsInString = 8;
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800490static_assert(alignof(std::string) <= alignof(void *),
491 "unexpectedly large std::string alignment");
David Tolnay06677b32020-11-23 18:05:45 -0800492static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800493 "unexpectedly large std::string size");
David Tolnayc26de542020-11-23 18:18:19 -0800494} // namespace
David Tolnaybb3ff5d2020-11-15 19:45:11 -0800495
David Tolnay37dd7e12020-04-25 12:51:59 -0700496#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800497 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
David Tolnay37dd7e12020-04-25 12:51:59 -0700498 const std::vector<CXX_TYPE> &s) noexcept { \
499 return s.size(); \
500 } \
David Tolnay767e00d2020-12-21 17:12:27 -0800501 CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
502 std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
503 return &(*s)[pos]; \
David Tolnay37dd7e12020-04-25 12:51:59 -0700504 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800505 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
David Tolnay996db1e2020-04-24 14:46:31 -0700506 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
507 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700508 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800509 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
David Tolnay996db1e2020-04-24 14:46:31 -0700510 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
David Tolnay37dd7e12020-04-25 12:51:59 -0700511 std::vector<CXX_TYPE> *raw) noexcept { \
David Tolnay996db1e2020-04-24 14:46:31 -0700512 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
David Tolnay37dd7e12020-04-25 12:51:59 -0700513 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700514 const std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800515 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
David Tolnay996db1e2020-04-24 14:46:31 -0700516 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700517 return ptr.get(); \
518 } \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700519 std::vector<CXX_TYPE> \
David Tolnay0f0162f2020-11-16 23:43:37 -0800520 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
David Tolnay996db1e2020-04-24 14:46:31 -0700521 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700522 return ptr.release(); \
523 } \
David Tolnay0f0162f2020-11-16 23:43:37 -0800524 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
David Tolnay996db1e2020-04-24 14:46:31 -0700525 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
David Tolnay37dd7e12020-04-25 12:51:59 -0700526 ptr->~unique_ptr(); \
David Tolnay4e7e7c42020-04-24 14:48:07 -0700527 }
Myron Ahneba35cf2020-02-05 19:41:51 +0700528
David Tolnayfc26d6d2021-04-15 21:18:45 -0700529#define STD_VECTOR_TRIVIAL_OPS(RUST_TYPE, CXX_TYPE) \
530 void cxxbridge1$std$vector$##RUST_TYPE##$push_back( \
531 std::vector<CXX_TYPE> *v, CXX_TYPE *value) noexcept { \
532 v->push_back(std::move(*value)); \
533 destroy(value); \
David Tolnay95215192021-04-16 15:40:12 -0700534 } \
535 void cxxbridge1$std$vector$##RUST_TYPE##$pop_back(std::vector<CXX_TYPE> *v, \
536 CXX_TYPE *out) noexcept { \
537 new (out) CXX_TYPE(std::move(v->back())); \
538 v->pop_back(); \
David Tolnayfc26d6d2021-04-15 21:18:45 -0700539 }
540
David Tolnay6787be62020-04-25 11:01:02 -0700541#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
David Tolnay0f0162f2020-11-16 23:43:37 -0800542 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
David Tolnayf97c2d52020-04-25 16:37:48 -0700543 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800544 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
David Tolnay6787be62020-04-25 11:01:02 -0700545 rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800546 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
David Tolnay6787be62020-04-25 11:01:02 -0700547 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800548 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
David Tolnaydc62d712020-12-11 13:51:53 -0800549 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800550 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
David Tolnay6787be62020-04-25 11:01:02 -0700551 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800552 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
David Tolnaya7bde2b2021-08-27 12:00:20 -0700553 rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
David Tolnay0f0162f2020-11-16 23:43:37 -0800554 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
David Tolnaye1df7dd2020-12-27 02:51:51 -0800555 std::size_t len) noexcept;
David Tolnay6787be62020-04-25 11:01:02 -0700556
557#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
558 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700559 Vec<CXX_TYPE>::Vec() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800560 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
David Tolnayf97c2d52020-04-25 16:37:48 -0700561 } \
562 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700563 void Vec<CXX_TYPE>::drop() noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800564 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700565 } \
566 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800567 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800568 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700569 } \
570 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800571 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
David Tolnaydc62d712020-12-11 13:51:53 -0800572 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
573 } \
574 template <> \
David Tolnay1768d8f2020-04-25 18:15:11 -0700575 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800576 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
David Tolnay6787be62020-04-25 11:01:02 -0700577 } \
578 template <> \
David Tolnaya7bde2b2021-08-27 12:00:20 -0700579 void Vec<CXX_TYPE>::reserve_total(std::size_t new_cap) noexcept { \
580 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, new_cap); \
David Tolnayfb6b73c2020-11-10 14:32:16 -0800581 } \
582 template <> \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800583 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
David Tolnay0f0162f2020-11-16 23:43:37 -0800584 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
David Tolnay6787be62020-04-25 11:01:02 -0700585 }
586
David Tolnay5b163402020-12-10 19:26:02 -0800587#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
588 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
589 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
590 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
591 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
592 new (ptr) std::shared_ptr<CXX_TYPE>(); \
593 } \
594 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
595 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
596 CXX_TYPE *uninit = \
597 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
598 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
599 return uninit; \
600 } \
601 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
602 const std::shared_ptr<CXX_TYPE> &self, \
603 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
604 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
605 } \
606 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
607 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
608 return self.get(); \
609 } \
610 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
611 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
612 self->~shared_ptr(); \
David Tolnay215e77f2020-12-28 17:09:48 -0800613 } \
614 static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
615 static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
616 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
617 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
618 new (ptr) std::weak_ptr<CXX_TYPE>(); \
619 } \
620 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
621 const std::weak_ptr<CXX_TYPE> &self, \
622 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
623 new (ptr) std::weak_ptr<CXX_TYPE>(self); \
624 } \
David Tolnay85b6bc42020-12-28 17:47:51 -0800625 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
626 const std::shared_ptr<CXX_TYPE> &shared, \
627 std::weak_ptr<CXX_TYPE> *weak) noexcept { \
628 new (weak) std::weak_ptr<CXX_TYPE>(shared); \
629 } \
David Tolnay7a487852020-12-28 18:02:25 -0800630 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
631 const std::weak_ptr<CXX_TYPE> &weak, \
632 std::shared_ptr<CXX_TYPE> *shared) noexcept { \
633 new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
634 } \
David Tolnay215e77f2020-12-28 17:09:48 -0800635 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
636 const std::weak_ptr<CXX_TYPE> *self) noexcept { \
637 self->~weak_ptr(); \
David Tolnay5b163402020-12-10 19:26:02 -0800638 }
639
David Tolnay6787be62020-04-25 11:01:02 -0700640// Usize and isize are the same type as one of the below.
David Tolnayf336b3b2020-04-30 08:45:54 -0700641#define FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800642 MACRO(u8, std::uint8_t) \
643 MACRO(u16, std::uint16_t) \
644 MACRO(u32, std::uint32_t) \
645 MACRO(u64, std::uint64_t) \
646 MACRO(i8, std::int8_t) \
647 MACRO(i16, std::int16_t) \
648 MACRO(i32, std::int32_t) \
649 MACRO(i64, std::int64_t) \
David Tolnay6787be62020-04-25 11:01:02 -0700650 MACRO(f32, float) \
651 MACRO(f64, double)
652
David Tolnayfc26d6d2021-04-15 21:18:45 -0700653#define FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
David Tolnayf336b3b2020-04-30 08:45:54 -0700654 FOR_EACH_NUMERIC(MACRO) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800655 MACRO(usize, std::size_t) \
David Tolnayfc26d6d2021-04-15 21:18:45 -0700656 MACRO(isize, rust::isize)
657
658#define FOR_EACH_STD_VECTOR(MACRO) \
659 FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
David Tolnay47e239d2020-08-28 00:32:04 -0700660 MACRO(string, std::string)
David Tolnay6787be62020-04-25 11:01:02 -0700661
David Tolnayf336b3b2020-04-30 08:45:54 -0700662#define FOR_EACH_RUST_VEC(MACRO) \
663 FOR_EACH_NUMERIC(MACRO) \
David Tolnay33f56ad2020-08-27 17:06:35 -0700664 MACRO(bool, bool) \
David Tolnay93e71d02020-11-25 20:16:52 -0800665 MACRO(char, char) \
David Tolnay60f83592021-02-08 23:00:01 -0800666 MACRO(usize, rust::detail::usize_if_unique) \
667 MACRO(isize, rust::detail::isize_if_unique) \
David Tolnay2d1fcc22021-01-03 22:43:19 -0800668 MACRO(string, rust::String) \
669 MACRO(str, rust::Str)
David Tolnayf336b3b2020-04-30 08:45:54 -0700670
David Tolnay5b163402020-12-10 19:26:02 -0800671#define FOR_EACH_SHARED_PTR(MACRO) \
672 FOR_EACH_NUMERIC(MACRO) \
David Tolnaycd1430c2020-12-28 17:17:14 -0800673 MACRO(bool, bool) \
David Tolnaybe3cbf72020-12-12 22:12:07 -0800674 MACRO(usize, std::size_t) \
David Tolnay5b163402020-12-10 19:26:02 -0800675 MACRO(isize, rust::isize) \
676 MACRO(string, std::string)
677
David Tolnay4e7e7c42020-04-24 14:48:07 -0700678extern "C" {
David Tolnayf336b3b2020-04-30 08:45:54 -0700679FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
David Tolnayfc26d6d2021-04-15 21:18:45 -0700680FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS)
David Tolnayf336b3b2020-04-30 08:45:54 -0700681FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
David Tolnay5b163402020-12-10 19:26:02 -0800682FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
David Tolnay4e7e7c42020-04-24 14:48:07 -0700683} // extern "C"
David Tolnay6787be62020-04-25 11:01:02 -0700684
David Tolnay1768d8f2020-04-25 18:15:11 -0700685namespace rust {
David Tolnay0f0162f2020-11-16 23:43:37 -0800686inline namespace cxxbridge1 {
David Tolnayf336b3b2020-04-30 08:45:54 -0700687FOR_EACH_RUST_VEC(RUST_VEC_OPS)
David Tolnay0f0162f2020-11-16 23:43:37 -0800688} // namespace cxxbridge1
David Tolnay1768d8f2020-04-25 18:15:11 -0700689} // namespace rust