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