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 this->msg = other.msg;
492 this->len = other.len;
493 other.msg = nullptr;
494 other.len = 0;
495 return *this;
496 }
497
what() const498 const char *Error::what() const noexcept { return this->msg; }
499
500 namespace {
501 template <typename T>
502 union MaybeUninit {
503 T value;
MaybeUninit()504 MaybeUninit() {}
~MaybeUninit()505 ~MaybeUninit() {}
506 };
507 } // namespace
508
509 namespace repr {
510 struct PtrLen final {
511 void *ptr;
512 std::size_t len;
513 };
514 } // namespace repr
515
516 extern "C" {
517 repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept;
518 }
519
520 namespace detail {
521 // On some platforms size_t is the same C++ type as one of the sized integer
522 // types; on others it is a distinct type. Only in the latter case do we need to
523 // define a specialized impl of rust::Vec<size_t>, because in the former case it
524 // would collide with one of the other specializations.
525 using usize_if_unique =
526 typename std::conditional<std::is_same<size_t, uint64_t>::value ||
527 std::is_same<size_t, uint32_t>::value,
528 struct usize_ignore, size_t>::type;
529 using isize_if_unique =
530 typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
531 std::is_same<rust::isize, int32_t>::value,
532 struct isize_ignore, rust::isize>::type;
533
534 class Fail final {
535 repr::PtrLen &throw$;
536
537 public:
Fail(repr::PtrLen & throw$)538 Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
539 void operator()(const char *) noexcept;
540 void operator()(const std::string &) noexcept;
541 };
542
operator ()(const char * catch$)543 void Fail::operator()(const char *catch$) noexcept {
544 throw$ = cxxbridge1$exception(catch$, std::strlen(catch$));
545 }
546
operator ()(const std::string & catch$)547 void Fail::operator()(const std::string &catch$) noexcept {
548 throw$ = cxxbridge1$exception(catch$.data(), catch$.length());
549 }
550 } // namespace detail
551
552 } // namespace cxxbridge1
553 } // namespace rust
554
555 namespace {
556 template <typename T>
destroy(T * ptr)557 void destroy(T *ptr) {
558 ptr->~T();
559 }
560 } // namespace
561
562 extern "C" {
cxxbridge1$unique_ptr$std$string$null(std::unique_ptr<std::string> * ptr)563 void cxxbridge1$unique_ptr$std$string$null(
564 std::unique_ptr<std::string> *ptr) noexcept {
565 new (ptr) std::unique_ptr<std::string>();
566 }
cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> * ptr,std::string * raw)567 void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
568 std::string *raw) noexcept {
569 new (ptr) std::unique_ptr<std::string>(raw);
570 }
cxxbridge1$unique_ptr$std$string$get(const std::unique_ptr<std::string> & ptr)571 const std::string *cxxbridge1$unique_ptr$std$string$get(
572 const std::unique_ptr<std::string> &ptr) noexcept {
573 return ptr.get();
574 }
cxxbridge1$unique_ptr$std$string$release(std::unique_ptr<std::string> & ptr)575 std::string *cxxbridge1$unique_ptr$std$string$release(
576 std::unique_ptr<std::string> &ptr) noexcept {
577 return ptr.release();
578 }
cxxbridge1$unique_ptr$std$string$drop(std::unique_ptr<std::string> * ptr)579 void cxxbridge1$unique_ptr$std$string$drop(
580 std::unique_ptr<std::string> *ptr) noexcept {
581 ptr->~unique_ptr();
582 }
583 } // extern "C"
584
585 namespace {
586 const std::size_t kMaxExpectedWordsInString = 8;
587 static_assert(alignof(std::string) <= alignof(void *),
588 "unexpectedly large std::string alignment");
589 static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
590 "unexpectedly large std::string size");
591 } // namespace
592
593 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
594 std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \
595 const std::vector<CXX_TYPE> &s) noexcept { \
596 return s.size(); \
597 } \
598 CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \
599 std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \
600 return &(*s)[pos]; \
601 } \
602 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \
603 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
604 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \
605 } \
606 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \
607 std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \
608 std::vector<CXX_TYPE> *raw) noexcept { \
609 new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
610 } \
611 const std::vector<CXX_TYPE> \
612 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \
613 const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
614 return ptr.get(); \
615 } \
616 std::vector<CXX_TYPE> \
617 *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \
618 std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \
619 return ptr.release(); \
620 } \
621 void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \
622 std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
623 ptr->~unique_ptr(); \
624 }
625
626 #define STD_VECTOR_TRIVIAL_OPS(RUST_TYPE, CXX_TYPE) \
627 void cxxbridge1$std$vector$##RUST_TYPE##$push_back( \
628 std::vector<CXX_TYPE> *v, CXX_TYPE *value) noexcept { \
629 v->push_back(std::move(*value)); \
630 destroy(value); \
631 } \
632 void cxxbridge1$std$vector$##RUST_TYPE##$pop_back(std::vector<CXX_TYPE> *v, \
633 CXX_TYPE *out) noexcept { \
634 new (out) CXX_TYPE(std::move(v->back())); \
635 v->pop_back(); \
636 }
637
638 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \
639 void cxxbridge1$rust_vec$##RUST_TYPE##$new( \
640 rust::Vec<CXX_TYPE> *ptr) noexcept; \
641 void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \
642 rust::Vec<CXX_TYPE> *ptr) noexcept; \
643 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \
644 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
645 std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \
646 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
647 const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \
648 const rust::Vec<CXX_TYPE> *ptr) noexcept; \
649 void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
650 rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
651 void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
652 std::size_t len) noexcept; \
653 void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \
654 std::size_t len) noexcept;
655
656 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
657 template <> \
658 Vec<CXX_TYPE>::Vec() noexcept { \
659 cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \
660 } \
661 template <> \
662 void Vec<CXX_TYPE>::drop() noexcept { \
663 return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \
664 } \
665 template <> \
666 std::size_t Vec<CXX_TYPE>::size() const noexcept { \
667 return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \
668 } \
669 template <> \
670 std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \
671 return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \
672 } \
673 template <> \
674 const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \
675 return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \
676 } \
677 template <> \
678 void Vec<CXX_TYPE>::reserve_total(std::size_t new_cap) noexcept { \
679 cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, new_cap); \
680 } \
681 template <> \
682 void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
683 cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
684 } \
685 template <> \
686 void Vec<CXX_TYPE>::truncate(std::size_t len) { \
687 cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \
688 }
689
690 #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
691 static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
692 static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
693 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
694 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
695 new (ptr) std::shared_ptr<CXX_TYPE>(); \
696 } \
697 CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
698 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
699 CXX_TYPE *uninit = \
700 reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
701 new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
702 return uninit; \
703 } \
704 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
705 const std::shared_ptr<CXX_TYPE> &self, \
706 std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
707 new (ptr) std::shared_ptr<CXX_TYPE>(self); \
708 } \
709 const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
710 const std::shared_ptr<CXX_TYPE> &self) noexcept { \
711 return self.get(); \
712 } \
713 void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
714 const std::shared_ptr<CXX_TYPE> *self) noexcept { \
715 self->~shared_ptr(); \
716 } \
717 static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
718 static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \
719 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \
720 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
721 new (ptr) std::weak_ptr<CXX_TYPE>(); \
722 } \
723 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \
724 const std::weak_ptr<CXX_TYPE> &self, \
725 std::weak_ptr<CXX_TYPE> *ptr) noexcept { \
726 new (ptr) std::weak_ptr<CXX_TYPE>(self); \
727 } \
728 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \
729 const std::shared_ptr<CXX_TYPE> &shared, \
730 std::weak_ptr<CXX_TYPE> *weak) noexcept { \
731 new (weak) std::weak_ptr<CXX_TYPE>(shared); \
732 } \
733 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \
734 const std::weak_ptr<CXX_TYPE> &weak, \
735 std::shared_ptr<CXX_TYPE> *shared) noexcept { \
736 new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \
737 } \
738 void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \
739 const std::weak_ptr<CXX_TYPE> *self) noexcept { \
740 self->~weak_ptr(); \
741 }
742
743 // Usize and isize are the same type as one of the below.
744 #define FOR_EACH_NUMERIC(MACRO) \
745 MACRO(u8, std::uint8_t) \
746 MACRO(u16, std::uint16_t) \
747 MACRO(u32, std::uint32_t) \
748 MACRO(u64, std::uint64_t) \
749 MACRO(i8, std::int8_t) \
750 MACRO(i16, std::int16_t) \
751 MACRO(i32, std::int32_t) \
752 MACRO(i64, std::int64_t) \
753 MACRO(f32, float) \
754 MACRO(f64, double)
755
756 #define FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
757 FOR_EACH_NUMERIC(MACRO) \
758 MACRO(usize, std::size_t) \
759 MACRO(isize, rust::isize)
760
761 #define FOR_EACH_STD_VECTOR(MACRO) \
762 FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \
763 MACRO(string, std::string)
764
765 #define FOR_EACH_RUST_VEC(MACRO) \
766 FOR_EACH_NUMERIC(MACRO) \
767 MACRO(bool, bool) \
768 MACRO(char, char) \
769 MACRO(usize, rust::detail::usize_if_unique) \
770 MACRO(isize, rust::detail::isize_if_unique) \
771 MACRO(string, rust::String) \
772 MACRO(str, rust::Str)
773
774 #define FOR_EACH_SHARED_PTR(MACRO) \
775 FOR_EACH_NUMERIC(MACRO) \
776 MACRO(bool, bool) \
777 MACRO(usize, std::size_t) \
778 MACRO(isize, rust::isize) \
779 MACRO(string, std::string)
780
781 extern "C" {
782 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
783 FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS)
784 FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
785 FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
786 } // extern "C"
787
788 namespace rust {
789 inline namespace cxxbridge1 {
790 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
791 } // namespace cxxbridge1
792 } // namespace rust
793