1 #include "../include/cxx.h"
2 #include <cstdio>
3 #include <cstring>
4 #include <iostream>
5 #include <memory>
6
7 extern "C" {
cxxbridge1$cxx_string$init(std::string * s,const std::uint8_t * ptr,std::size_t len)8 void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
9 std::size_t len) noexcept {
10 new (s) std::string(reinterpret_cast<const char *>(ptr), len);
11 }
12
cxxbridge1$cxx_string$destroy(std::string * s)13 void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
14 using std::string;
15 s->~string();
16 }
17
cxxbridge1$cxx_string$data(const std::string & s)18 const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
19 return s.data();
20 }
21
cxxbridge1$cxx_string$length(const std::string & s)22 std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
23 return s.length();
24 }
25
cxxbridge1$cxx_string$clear(std::string & s)26 void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
27
cxxbridge1$cxx_string$reserve_total(std::string & s,size_t new_cap)28 void cxxbridge1$cxx_string$reserve_total(std::string &s,
29 size_t new_cap) noexcept {
30 s.reserve(new_cap);
31 }
32
cxxbridge1$cxx_string$push(std::string & s,const std::uint8_t * ptr,std::size_t len)33 void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
34 std::size_t len) noexcept {
35 s.append(reinterpret_cast<const char *>(ptr), len);
36 }
37
38 // rust::String
39 void cxxbridge1$string$new(rust::String *self) noexcept;
40 void cxxbridge1$string$clone(rust::String *self,
41 const rust::String &other) noexcept;
42 bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr,
43 std::size_t len) noexcept;
44 void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr,
45 std::size_t len) noexcept;
46 bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr,
47 std::size_t len) noexcept;
48 void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr,
49 std::size_t len) noexcept;
50 void cxxbridge1$string$drop(rust::String *self) noexcept;
51 const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
52 std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
53 std::size_t cxxbridge1$string$capacity(const rust::String *self) noexcept;
54 void cxxbridge1$string$reserve_additional(rust::String *self,
55 size_t additional) noexcept;
56 void cxxbridge1$string$reserve_total(rust::String *self,
57 size_t new_cap) noexcept;
58
59 // rust::Str
60 void cxxbridge1$str$new(rust::Str *self) noexcept;
61 void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
62 bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
63 std::size_t len) noexcept;
64 const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
65 std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
66
67 // rust::Slice
68 void cxxbridge1$slice$new(void *self, const void *ptr,
69 std::size_t len) noexcept;
70 void *cxxbridge1$slice$ptr(const void *self) noexcept;
71 std::size_t cxxbridge1$slice$len(const void *self) noexcept;
72 } // extern "C"
73
74 namespace rust {
75 inline namespace cxxbridge1 {
76
77 template <typename Exception>
panic(const char * msg)78 void panic [[noreturn]] (const char *msg) {
79 #if defined(RUST_CXX_NO_EXCEPTIONS)
80 std::fprintf(stderr, "Error: %s. Aborting.\n", msg);
81 std::abort();
82 #else
83 throw Exception(msg);
84 #endif
85 }
86
87 template void panic<std::out_of_range> [[noreturn]] (const char *msg);
88
89 template <typename T>
is_aligned(const void * ptr)90 static bool is_aligned(const void *ptr) noexcept {
91 auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
92 return !(iptr % alignof(T));
93 }
94
String()95 String::String() noexcept { cxxbridge1$string$new(this); }
96
String(const String & other)97 String::String(const String &other) noexcept {
98 cxxbridge1$string$clone(this, other);
99 }
100
String(String && other)101 String::String(String &&other) noexcept : repr(other.repr) {
102 cxxbridge1$string$new(&other);
103 }
104
~String()105 String::~String() noexcept { cxxbridge1$string$drop(this); }
106
initString(String * self,const char * s,std::size_t len)107 static void initString(String *self, const char *s, std::size_t len) {
108 if (!cxxbridge1$string$from_utf8(self, s, len)) {
109 panic<std::invalid_argument>("data for rust::String is not utf-8");
110 }
111 }
112
initString(String * self,const char16_t * s,std::size_t len)113 static void initString(String *self, const char16_t *s, std::size_t len) {
114 if (!cxxbridge1$string$from_utf16(self, s, len)) {
115 panic<std::invalid_argument>("data for rust::String is not utf-16");
116 }
117 }
118
String(const std::string & s)119 String::String(const std::string &s) { initString(this, s.data(), s.length()); }
120
String(const char * s)121 String::String(const char *s) {
122 assert(s != nullptr);
123 initString(this, s, std::strlen(s));
124 }
125
String(const char * s,std::size_t len)126 String::String(const char *s, std::size_t len) {
127 assert(s != nullptr || len == 0);
128 initString(this,
129 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
130 len);
131 }
132
String(const char16_t * s)133 String::String(const char16_t *s) {
134 assert(s != nullptr);
135 assert(is_aligned<char16_t>(s));
136 initString(this, s, std::char_traits<char16_t>::length(s));
137 }
138
String(const char16_t * s,std::size_t len)139 String::String(const char16_t *s, std::size_t len) {
140 assert(s != nullptr || len == 0);
141 assert(is_aligned<char16_t>(s));
142 initString(this,
143 s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2)
144 : s,
145 len);
146 }
147
148 struct String::lossy_t {};
149
String(lossy_t,const char * s,std::size_t len)150 String::String(lossy_t, const char *s, std::size_t len) noexcept {
151 cxxbridge1$string$from_utf8_lossy(
152 this, s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
153 len);
154 }
155
String(lossy_t,const char16_t * s,std::size_t len)156 String::String(lossy_t, const char16_t *s, std::size_t len) noexcept {
157 cxxbridge1$string$from_utf16_lossy(
158 this,
159 s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s,
160 len);
161 }
162
lossy(const std::string & s)163 String String::lossy(const std::string &s) noexcept {
164 return String::lossy(s.data(), s.length());
165 }
166
lossy(const char * s)167 String String::lossy(const char *s) noexcept {
168 assert(s != nullptr);
169 return String::lossy(s, std::strlen(s));
170 }
171
lossy(const char * s,std::size_t len)172 String String::lossy(const char *s, std::size_t len) noexcept {
173 assert(s != nullptr || len == 0);
174 return String(lossy_t{}, s, len);
175 }
176
lossy(const char16_t * s)177 String String::lossy(const char16_t *s) noexcept {
178 assert(s != nullptr);
179 assert(is_aligned<char16_t>(s));
180 return String(lossy_t{}, s, std::char_traits<char16_t>::length(s));
181 }
182
lossy(const char16_t * s,std::size_t len)183 String String::lossy(const char16_t *s, std::size_t len) noexcept {
184 assert(s != nullptr || len == 0);
185 assert(is_aligned<char16_t>(s));
186 return String(lossy_t{}, s, len);
187 }
188
operator =(const String & other)189 String &String::operator=(const String &other) &noexcept {
190 if (this != &other) {
191 cxxbridge1$string$drop(this);
192 cxxbridge1$string$clone(this, other);
193 }
194 return *this;
195 }
196
operator =(String && other)197 String &String::operator=(String &&other) &noexcept {
198 cxxbridge1$string$drop(this);
199 this->repr = other.repr;
200 cxxbridge1$string$new(&other);
201 return *this;
202 }
203
operator std::string() const204 String::operator std::string() const {
205 return std::string(this->data(), this->size());
206 }
207
data() const208 const char *String::data() const noexcept {
209 return cxxbridge1$string$ptr(this);
210 }
211
size() const212 std::size_t String::size() const noexcept {
213 return cxxbridge1$string$len(this);
214 }
215
length() const216 std::size_t String::length() const noexcept {
217 return cxxbridge1$string$len(this);
218 }
219
empty() const220 bool String::empty() const noexcept { return this->size() == 0; }
221
c_str()222 const char *String::c_str() noexcept {
223 auto len = this->length();
224 cxxbridge1$string$reserve_additional(this, 1);
225 auto ptr = this->data();
226 const_cast<char *>(ptr)[len] = '\0';
227 return ptr;
228 }
229
capacity() const230 std::size_t String::capacity() const noexcept {
231 return cxxbridge1$string$capacity(this);
232 }
233
reserve(std::size_t new_cap)234 void String::reserve(std::size_t new_cap) noexcept {
235 cxxbridge1$string$reserve_total(this, new_cap);
236 }
237
begin()238 String::iterator String::begin() noexcept {
239 return const_cast<char *>(this->data());
240 }
241
end()242 String::iterator String::end() noexcept {
243 return const_cast<char *>(this->data()) + this->size();
244 }
245
begin() const246 String::const_iterator String::begin() const noexcept { return this->cbegin(); }
247
end() const248 String::const_iterator String::end() const noexcept { return this->cend(); }
249
cbegin() const250 String::const_iterator String::cbegin() const noexcept { return this->data(); }
251
cend() const252 String::const_iterator String::cend() const noexcept {
253 return this->data() + this->size();
254 }
255
operator ==(const String & rhs) const256 bool String::operator==(const String &rhs) const noexcept {
257 return rust::Str(*this) == rust::Str(rhs);
258 }
259
operator !=(const String & rhs) const260 bool String::operator!=(const String &rhs) const noexcept {
261 return rust::Str(*this) != rust::Str(rhs);
262 }
263
operator <(const String & rhs) const264 bool String::operator<(const String &rhs) const noexcept {
265 return rust::Str(*this) < rust::Str(rhs);
266 }
267
operator <=(const String & rhs) const268 bool String::operator<=(const String &rhs) const noexcept {
269 return rust::Str(*this) <= rust::Str(rhs);
270 }
271
operator >(const String & rhs) const272 bool String::operator>(const String &rhs) const noexcept {
273 return rust::Str(*this) > rust::Str(rhs);
274 }
275
operator >=(const String & rhs) const276 bool String::operator>=(const String &rhs) const noexcept {
277 return rust::Str(*this) >= rust::Str(rhs);
278 }
279
swap(String & rhs)280 void String::swap(String &rhs) noexcept {
281 using std::swap;
282 swap(this->repr, rhs.repr);
283 }
284
String(unsafe_bitcopy_t,const String & bits)285 String::String(unsafe_bitcopy_t, const String &bits) noexcept
286 : repr(bits.repr) {}
287
operator <<(std::ostream & os,const String & s)288 std::ostream &operator<<(std::ostream &os, const String &s) {
289 os.write(s.data(), static_cast<std::streamsize>(s.size()));
290 return os;
291 }
292
Str()293 Str::Str() noexcept { cxxbridge1$str$new(this); }
294
Str(const String & s)295 Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
296
initStr(Str * self,const char * ptr,std::size_t len)297 static void initStr(Str *self, const char *ptr, std::size_t len) {
298 if (!cxxbridge1$str$from(self, ptr, len)) {
299 panic<std::invalid_argument>("data for rust::Str is not utf-8");
300 }
301 }
302
Str(const std::string & s)303 Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
304
Str(const char * s)305 Str::Str(const char *s) {
306 assert(s != nullptr);
307 initStr(this, s, std::strlen(s));
308 }
309
Str(const char * s,std::size_t len)310 Str::Str(const char *s, std::size_t len) {
311 assert(s != nullptr || len == 0);
312 initStr(this,
313 s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
314 len);
315 }
316
operator std::string() const317 Str::operator std::string() const {
318 return std::string(this->data(), this->size());
319 }
320
data() const321 const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
322
size() const323 std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
324
length() const325 std::size_t Str::length() const noexcept { return this->size(); }
326
empty() const327 bool Str::empty() const noexcept { return this->size() == 0; }
328
begin() const329 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
330
end() const331 Str::const_iterator Str::end() const noexcept { return this->cend(); }
332
cbegin() const333 Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
334
cend() const335 Str::const_iterator Str::cend() const noexcept {
336 return this->data() + this->size();
337 }
338
operator ==(const Str & rhs) const339 bool Str::operator==(const Str &rhs) const noexcept {
340 return this->size() == rhs.size() &&
341 std::equal(this->begin(), this->end(), rhs.begin());
342 }
343
operator !=(const Str & rhs) const344 bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
345
operator <(const Str & rhs) const346 bool Str::operator<(const Str &rhs) const noexcept {
347 return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
348 rhs.end());
349 }
350
operator <=(const Str & rhs) const351 bool Str::operator<=(const Str &rhs) const noexcept {
352 // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
353 // without Undefined Behavior on C++11 if rhs is shorter than *this.
354 const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
355 rend = rhs.end();
356 while (liter != lend && riter != rend && *liter == *riter) {
357 ++liter, ++riter;
358 }
359 if (liter == lend) {
360 return true; // equal or *this is a prefix of rhs
361 } else if (riter == rend) {
362 return false; // rhs is a prefix of *this
363 } else {
364 return *liter <= *riter;
365 }
366 }
367
operator >(const Str & rhs) const368 bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
369
operator >=(const Str & rhs) const370 bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
371
swap(Str & rhs)372 void Str::swap(Str &rhs) noexcept {
373 using std::swap;
374 swap(this->repr, rhs.repr);
375 }
376
operator <<(std::ostream & os,const Str & s)377 std::ostream &operator<<(std::ostream &os, const Str &s) {
378 os.write(s.data(), static_cast<std::streamsize>(s.size()));
379 return os;
380 }
381
sliceInit(void * self,const void * ptr,std::size_t len)382 void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
383 cxxbridge1$slice$new(self, ptr, len);
384 }
385
slicePtr(const void * self)386 void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
387
sliceLen(const void * self)388 std::size_t sliceLen(const void *self) noexcept {
389 return cxxbridge1$slice$len(self);
390 }
391
392 // Rust specifies that usize is ABI compatible with C's uintptr_t.
393 // https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
394 // However there is no direct Rust equivalent for size_t. C does not guarantee
395 // that size_t and uintptr_t are compatible. In practice though, on all
396 // platforms supported by Rust, they are identical for ABI purposes. See the
397 // libc crate which unconditionally defines libc::size_t = usize. We expect the
398 // same here and these assertions are just here to explicitly document that.
399 // *Note that no assumption is made about C++ name mangling of signatures
400 // containing these types, not here nor anywhere in CXX.*
401 static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
402 "unsupported size_t size");
403 static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
404 "unsupported size_t alignment");
405 static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
406 "unsupported ssize_t size");
407 static_assert(alignof(rust::isize) == alignof(std::intptr_t),
408 "unsupported ssize_t alignment");
409
410 static_assert(std::is_trivially_copy_constructible<Str>::value,
411 "trivial Str(const Str &)");
412 static_assert(std::is_trivially_copy_assignable<Str>::value,
413 "trivial operator=(const Str &)");
414 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
415
416 static_assert(
417 std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
418 "trivial Slice(const Slice &)");
419 static_assert(
420 std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
421 "trivial Slice(Slice &&)");
422 static_assert(
423 std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
424 "trivial Slice::operator=(const Slice &) for const slices");
425 static_assert(
426 std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
427 "trivial Slice::operator=(Slice &&)");
428 static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
429 "trivial ~Slice()");
430
431 static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
432 "trivial Slice(const Slice &)");
433 static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
434 "trivial Slice(Slice &&)");
435 static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
436 "delete Slice::operator=(const Slice &) for mut slices");
437 static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
438 "trivial Slice::operator=(Slice &&)");
439 static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
440 "trivial ~Slice()");
441
442 static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
443 Vec<const std::uint8_t>::iterator>::value,
444 "Vec<T>::const_iterator == Vec<const T>::iterator");
445 static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
446 Vec<const std::uint8_t>::iterator>::value,
447 "Vec<const T>::const_iterator == Vec<const T>::iterator");
448 static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
449 Vec<std::uint8_t>::iterator>::value,
450 "Vec<T>::const_iterator != Vec<T>::iterator");
451
errorCopy(const char * ptr,std::size_t len)452 static const char *errorCopy(const char *ptr, std::size_t len) {
453 char *copy = new char[len];
454 std::memcpy(copy, ptr, len);
455 return copy;
456 }
457
458 extern "C" {
cxxbridge1$error(const char * ptr,std::size_t len)459 const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
460 return errorCopy(ptr, len);
461 }
462 } // extern "C"
463
Error(const Error & other)464 Error::Error(const Error &other)
465 : std::exception(other),
466 msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
467 len(other.len) {}
468
Error(Error && other)469 Error::Error(Error &&other) noexcept
470 : std::exception(std::move(other)), msg(other.msg), len(other.len) {
471 other.msg = nullptr;
472 other.len = 0;
473 }
474
~Error()475 Error::~Error() noexcept { delete[] this->msg; }
476
operator =(const Error & other)477 Error &Error::operator=(const Error &other) & {
478 if (this != &other) {
479 std::exception::operator=(other);
480 delete[] this->msg;
481 this->msg = nullptr;
482 if (other.msg) {
483 this->msg = errorCopy(other.msg, other.len);
484 this->len = other.len;
485 }
486 }
487 return *this;
488 }
489
operator =(Error && other)490 Error &Error::operator=(Error &&other) &noexcept {
491 std::exception::operator=(std::move(other));
492 delete[] this->msg;
493 this->msg = other.msg;
494 this->len = other.len;
495 other.msg = nullptr;
496 other.len = 0;
497 return *this;
498 }
499
what() const500 const char *Error::what() const noexcept { return this->msg; }
501
502 namespace {
503 template <typename T>
504 union MaybeUninit {
505 T value;
MaybeUninit()506 MaybeUninit() {}
~MaybeUninit()507 ~MaybeUninit() {}
508 };
509 } // namespace
510
511 namespace repr {
512 struct PtrLen final {
513 void *ptr;
514 std::size_t len;
515 };
516 } // namespace repr
517
518 extern "C" {
519 repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept;
520 }
521
522 namespace detail {
523 // On some platforms size_t is the same C++ type as one of the sized integer
524 // types; on others it is a distinct type. Only in the latter case do we need to
525 // define a specialized impl of rust::Vec<size_t>, because in the former case it
526 // would collide with one of the other specializations.
527 using usize_if_unique =
528 typename std::conditional<std::is_same<size_t, uint64_t>::value ||
529 std::is_same<size_t, uint32_t>::value,
530 struct usize_ignore, size_t>::type;
531 using isize_if_unique =
532 typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
533 std::is_same<rust::isize, int32_t>::value,
534 struct isize_ignore, rust::isize>::type;
535
536 class Fail final {
537 repr::PtrLen &throw$;
538
539 public:
Fail(repr::PtrLen & throw$)540 Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
541 void operator()(const char *) noexcept;
542 void operator()(const std::string &) noexcept;
543 };
544
operator ()(const char * catch$)545 void Fail::operator()(const char *catch$) noexcept {
546 throw$ = cxxbridge1$exception(catch$, std::strlen(catch$));
547 }
548
operator ()(const std::string & catch$)549 void Fail::operator()(const std::string &catch$) noexcept {
550 throw$ = cxxbridge1$exception(catch$.data(), catch$.length());
551 }
552 } // namespace detail
553
554 } // namespace cxxbridge1
555 } // namespace rust
556
557 namespace {
558 template <typename T>
destroy(T * ptr)559 void destroy(T *ptr) {
560 ptr->~T();
561 }
562 } // namespace
563
564 extern "C" {
cxxbridge1$unique_ptr$std$string$null(std::unique_ptr<std::string> * ptr)565 void cxxbridge1$unique_ptr$std$string$null(
566 std::unique_ptr<std::string> *ptr) noexcept {
567 new (ptr) std::unique_ptr<std::string>();
568 }
cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> * ptr,std::string * raw)569 void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
570 std::string *raw) noexcept {
571 new (ptr) std::unique_ptr<std::string>(raw);
572 }
cxxbridge1$unique_ptr$std$string$get(const std::unique_ptr<std::string> & ptr)573 const std::string *cxxbridge1$unique_ptr$std$string$get(
574 const std::unique_ptr<std::string> &ptr) noexcept {
575 return ptr.get();
576 }
cxxbridge1$unique_ptr$std$string$release(std::unique_ptr<std::string> & ptr)577 std::string *cxxbridge1$unique_ptr$std$string$release(
578 std::unique_ptr<std::string> &ptr) noexcept {
579 return ptr.release();
580 }
cxxbridge1$unique_ptr$std$string$drop(std::unique_ptr<std::string> * ptr)581 void cxxbridge1$unique_ptr$std$string$drop(
582 std::unique_ptr<std::string> *ptr) noexcept {
583 ptr->~unique_ptr();
584 }
585 } // extern "C"
586
587 namespace {
588 const std::size_t kMaxExpectedWordsInString = 8;
589 static_assert(alignof(std::string) <= alignof(void *),
590 "unexpectedly large std::string alignment");
591 static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
592 "unexpectedly large std::string size");
593 } // namespace
594
595 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
596 std::vector<CXX_TYPE> *cxxbridge1$std$vector$##RUST_TYPE##$new() noexcept { \
597 return new std::vector<CXX_TYPE>(); \
598 } \
599 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
600 const std::vector<CXX_TYPE> &s) noexcept { \
601 return s.size(); \
602 } \
603 CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
604 std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
605 return &(*s)[pos]; \
606 } \
607 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
608 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
609 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
610 } \
611 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
612 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
613 std::vector<CXX_TYPE> *raw) noexcept { \
614 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
615 } \
616 const std::vector<CXX_TYPE> \
617 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
618 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
619 return ptr.get(); \
620 } \
621 std::vector<CXX_TYPE> \
622 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
623 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
624 return ptr.release(); \
625 } \
626 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
627 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
628 ptr->~unique_ptr(); \
629 }
630
631 #define STD_VECTOR_TRIVIAL_OPS(RUST_TYPE, CXX_TYPE) \
632 void cxxbridge1$std$vector$##RUST_TYPE##$push_back( \
633 std::vector<CXX_TYPE> *v, CXX_TYPE *value) noexcept { \
634 v->push_back(std::move(*value)); \
635 destroy(value); \
636 } \
637 void cxxbridge1$std$vector$##RUST_TYPE##$pop_back(std::vector<CXX_TYPE> *v, \
638 CXX_TYPE *out) noexcept { \
639 new (out) CXX_TYPE(std::move(v->back())); \
640 v->pop_back(); \
641 }
642
643 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
644 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
645 rust::Vec<CXX_TYPE> *ptr) noexcept; \
646 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
647 rust::Vec<CXX_TYPE> *ptr) noexcept; \
648 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
649 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
650 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
651 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
652 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
653 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
654 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
655 rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
656 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
657 std::size_t len) noexcept; \
658 void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \
659 std::size_t len) noexcept;
660
661 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
662 template <> \
663 Vec<CXX_TYPE>::Vec() noexcept { \
664 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
665 } \
666 template <> \
667 void Vec<CXX_TYPE>::drop() noexcept { \
668 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
669 } \
670 template <> \
671 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
672 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
673 } \
674 template <> \
675 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
676 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
677 } \
678 template <> \
679 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
680 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
681 } \
682 template <> \
683 void Vec<CXX_TYPE>::reserve_total(std::size_t new_cap) noexcept { \
684 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, new_cap); \
685 } \
686 template <> \
687 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
688 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
689 } \
690 template <> \
691 void Vec<CXX_TYPE>::truncate(std::size_t len) { \
692 cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \
693 }
694
695 #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
696 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
697 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
698 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
699 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
700 new (ptr) std::shared_ptr<CXX_TYPE>(); \
701 } \
702 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
703 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
704 CXX_TYPE *uninit = \
705 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
706 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
707 return uninit; \
708 } \
709 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
710 const std::shared_ptr<CXX_TYPE> &self, \
711 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
712 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
713 } \
714 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
715 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
716 return self.get(); \
717 } \
718 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
719 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
720 self->~shared_ptr(); \
721 } \
722 static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
723 static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
724 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
725 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
726 new (ptr) std::weak_ptr<CXX_TYPE>(); \
727 } \
728 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
729 const std::weak_ptr<CXX_TYPE> &self, \
730 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
731 new (ptr) std::weak_ptr<CXX_TYPE>(self); \
732 } \
733 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
734 const std::shared_ptr<CXX_TYPE> &shared, \
735 std::weak_ptr<CXX_TYPE> *weak) noexcept { \
736 new (weak) std::weak_ptr<CXX_TYPE>(shared); \
737 } \
738 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
739 const std::weak_ptr<CXX_TYPE> &weak, \
740 std::shared_ptr<CXX_TYPE> *shared) noexcept { \
741 new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
742 } \
743 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
744 const std::weak_ptr<CXX_TYPE> *self) noexcept { \
745 self->~weak_ptr(); \
746 }
747
748 // Usize and isize are the same type as one of the below.
749 #define FOR_EACH_NUMERIC(MACRO) \
750 MACRO(u8, std::uint8_t) \
751 MACRO(u16, std::uint16_t) \
752 MACRO(u32, std::uint32_t) \
753 MACRO(u64, std::uint64_t) \
754 MACRO(i8, std::int8_t) \
755 MACRO(i16, std::int16_t) \
756 MACRO(i32, std::int32_t) \
757 MACRO(i64, std::int64_t) \
758 MACRO(f32, float) \
759 MACRO(f64, double)
760
761 #define FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
762 FOR_EACH_NUMERIC(MACRO) \
763 MACRO(usize, std::size_t) \
764 MACRO(isize, rust::isize)
765
766 #define FOR_EACH_STD_VECTOR(MACRO) \
767 FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
768 MACRO(string, std::string)
769
770 #define FOR_EACH_RUST_VEC(MACRO) \
771 FOR_EACH_NUMERIC(MACRO) \
772 MACRO(bool, bool) \
773 MACRO(char, char) \
774 MACRO(usize, rust::detail::usize_if_unique) \
775 MACRO(isize, rust::detail::isize_if_unique) \
776 MACRO(string, rust::String) \
777 MACRO(str, rust::Str)
778
779 #define FOR_EACH_SHARED_PTR(MACRO) \
780 FOR_EACH_NUMERIC(MACRO) \
781 MACRO(bool, bool) \
782 MACRO(usize, std::size_t) \
783 MACRO(isize, rust::isize) \
784 MACRO(string, std::string)
785
786 extern "C" {
787 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
788 FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS)
789 FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
790 FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
791 } // extern "C"
792
793 namespace rust {
794 inline namespace cxxbridge1 {
795 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
796 } // namespace cxxbridge1
797 } // namespace rust
798