xref: /third_party/rust/crates/cxx/src/cxx.cc (revision 33d722a9)
1#include "../include/cxx.h"
2#include <cstring>
3#include <iostream>
4#include <memory>
5
6extern "C" {
7void 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
12void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
13  using std::string;
14  s->~string();
15}
16
17const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
18  return s.data();
19}
20
21std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
22  return s.length();
23}
24
25void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); }
26
27void cxxbridge1$cxx_string$reserve_total(std::string &s,
28                                         size_t new_cap) noexcept {
29  s.reserve(new_cap);
30}
31
32void 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
38void cxxbridge1$string$new(rust::String *self) noexcept;
39void cxxbridge1$string$clone(rust::String *self,
40                             const rust::String &other) noexcept;
41bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr,
42                                 std::size_t len) noexcept;
43void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr,
44                                       std::size_t len) noexcept;
45bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr,
46                                  std::size_t len) noexcept;
47void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr,
48                                        std::size_t len) noexcept;
49void cxxbridge1$string$drop(rust::String *self) noexcept;
50const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
51std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
52std::size_t cxxbridge1$string$capacity(const rust::String *self) noexcept;
53void cxxbridge1$string$reserve_additional(rust::String *self,
54                                          size_t additional) noexcept;
55void cxxbridge1$string$reserve_total(rust::String *self,
56                                     size_t new_cap) noexcept;
57
58// rust::Str
59void cxxbridge1$str$new(rust::Str *self) noexcept;
60void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
61bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
62                         std::size_t len) noexcept;
63const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
64std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
65
66// rust::Slice
67void cxxbridge1$slice$new(void *self, const void *ptr,
68                          std::size_t len) noexcept;
69void *cxxbridge1$slice$ptr(const void *self) noexcept;
70std::size_t cxxbridge1$slice$len(const void *self) noexcept;
71} // extern "C"
72
73namespace rust {
74inline namespace cxxbridge1 {
75
76template <typename Exception>
77void 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
86template void panic<std::out_of_range> [[noreturn]] (const char *msg);
87
88template <typename T>
89static bool is_aligned(const void *ptr) noexcept {
90  auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
91  return !(iptr % alignof(T));
92}
93
94String::String() noexcept { cxxbridge1$string$new(this); }
95
96String::String(const String &other) noexcept {
97  cxxbridge1$string$clone(this, other);
98}
99
100String::String(String &&other) noexcept : repr(other.repr) {
101  cxxbridge1$string$new(&other);
102}
103
104String::~String() noexcept { cxxbridge1$string$drop(this); }
105
106static 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
112static 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
118String::String(const std::string &s) { initString(this, s.data(), s.length()); }
119
120String::String(const char *s) {
121  assert(s != nullptr);
122  initString(this, s, std::strlen(s));
123}
124
125String::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
132String::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
138String::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
147struct String::lossy_t {};
148
149String::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
155String::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
162String String::lossy(const std::string &s) noexcept {
163  return String::lossy(s.data(), s.length());
164}
165
166String String::lossy(const char *s) noexcept {
167  assert(s != nullptr);
168  return String::lossy(s, std::strlen(s));
169}
170
171String 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
176String 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
182String 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
188String &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
196String &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
203String::operator std::string() const {
204  return std::string(this->data(), this->size());
205}
206
207const char *String::data() const noexcept {
208  return cxxbridge1$string$ptr(this);
209}
210
211std::size_t String::size() const noexcept {
212  return cxxbridge1$string$len(this);
213}
214
215std::size_t String::length() const noexcept {
216  return cxxbridge1$string$len(this);
217}
218
219bool String::empty() const noexcept { return this->size() == 0; }
220
221const 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
229std::size_t String::capacity() const noexcept {
230  return cxxbridge1$string$capacity(this);
231}
232
233void String::reserve(std::size_t new_cap) noexcept {
234  cxxbridge1$string$reserve_total(this, new_cap);
235}
236
237String::iterator String::begin() noexcept {
238  return const_cast<char *>(this->data());
239}
240
241String::iterator String::end() noexcept {
242  return const_cast<char *>(this->data()) + this->size();
243}
244
245String::const_iterator String::begin() const noexcept { return this->cbegin(); }
246
247String::const_iterator String::end() const noexcept { return this->cend(); }
248
249String::const_iterator String::cbegin() const noexcept { return this->data(); }
250
251String::const_iterator String::cend() const noexcept {
252  return this->data() + this->size();
253}
254
255bool String::operator==(const String &rhs) const noexcept {
256  return rust::Str(*this) == rust::Str(rhs);
257}
258
259bool String::operator!=(const String &rhs) const noexcept {
260  return rust::Str(*this) != rust::Str(rhs);
261}
262
263bool String::operator<(const String &rhs) const noexcept {
264  return rust::Str(*this) < rust::Str(rhs);
265}
266
267bool String::operator<=(const String &rhs) const noexcept {
268  return rust::Str(*this) <= rust::Str(rhs);
269}
270
271bool String::operator>(const String &rhs) const noexcept {
272  return rust::Str(*this) > rust::Str(rhs);
273}
274
275bool String::operator>=(const String &rhs) const noexcept {
276  return rust::Str(*this) >= rust::Str(rhs);
277}
278
279void String::swap(String &rhs) noexcept {
280  using std::swap;
281  swap(this->repr, rhs.repr);
282}
283
284String::String(unsafe_bitcopy_t, const String &bits) noexcept
285    : repr(bits.repr) {}
286
287std::ostream &operator<<(std::ostream &os, const String &s) {
288  os.write(s.data(), static_cast<std::streamsize>(s.size()));
289  return os;
290}
291
292Str::Str() noexcept { cxxbridge1$str$new(this); }
293
294Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
295
296static 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
302Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
303
304Str::Str(const char *s) {
305  assert(s != nullptr);
306  initStr(this, s, std::strlen(s));
307}
308
309Str::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
316Str::operator std::string() const {
317  return std::string(this->data(), this->size());
318}
319
320const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
321
322std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
323
324std::size_t Str::length() const noexcept { return this->size(); }
325
326bool Str::empty() const noexcept { return this->size() == 0; }
327
328Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
329
330Str::const_iterator Str::end() const noexcept { return this->cend(); }
331
332Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
333
334Str::const_iterator Str::cend() const noexcept {
335  return this->data() + this->size();
336}
337
338bool Str::operator==(const Str &rhs) const noexcept {
339  return this->size() == rhs.size() &&
340         std::equal(this->begin(), this->end(), rhs.begin());
341}
342
343bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
344
345bool Str::operator<(const Str &rhs) const noexcept {
346  return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
347                                      rhs.end());
348}
349
350bool 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
367bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
368
369bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
370
371void Str::swap(Str &rhs) noexcept {
372  using std::swap;
373  swap(this->repr, rhs.repr);
374}
375
376std::ostream &operator<<(std::ostream &os, const Str &s) {
377  os.write(s.data(), static_cast<std::streamsize>(s.size()));
378  return os;
379}
380
381void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
382  cxxbridge1$slice$new(self, ptr, len);
383}
384
385void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
386
387std::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.*
400static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
401              "unsupported size_t size");
402static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
403              "unsupported size_t alignment");
404static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
405              "unsupported ssize_t size");
406static_assert(alignof(rust::isize) == alignof(std::intptr_t),
407              "unsupported ssize_t alignment");
408
409static_assert(std::is_trivially_copy_constructible<Str>::value,
410              "trivial Str(const Str &)");
411static_assert(std::is_trivially_copy_assignable<Str>::value,
412              "trivial operator=(const Str &)");
413static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
414
415static_assert(
416    std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
417    "trivial Slice(const Slice &)");
418static_assert(
419    std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
420    "trivial Slice(Slice &&)");
421static_assert(
422    std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
423    "trivial Slice::operator=(const Slice &) for const slices");
424static_assert(
425    std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
426    "trivial Slice::operator=(Slice &&)");
427static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
428              "trivial ~Slice()");
429
430static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
431              "trivial Slice(const Slice &)");
432static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
433              "trivial Slice(Slice &&)");
434static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
435              "delete Slice::operator=(const Slice &) for mut slices");
436static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
437              "trivial Slice::operator=(Slice &&)");
438static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
439              "trivial ~Slice()");
440
441static_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");
444static_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");
447static_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
451static 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
457extern "C" {
458const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
459  return errorCopy(ptr, len);
460}
461} // extern "C"
462
463Error::Error(const Error &other)
464    : std::exception(other),
465      msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
466      len(other.len) {}
467
468Error::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
474Error::~Error() noexcept { delete[] this->msg; }
475
476Error &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
489Error &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
499const char *Error::what() const noexcept { return this->msg; }
500
501namespace {
502template <typename T>
503union MaybeUninit {
504  T value;
505  MaybeUninit() {}
506  ~MaybeUninit() {}
507};
508} // namespace
509
510namespace repr {
511struct PtrLen final {
512  void *ptr;
513  std::size_t len;
514};
515} // namespace repr
516
517extern "C" {
518repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept;
519}
520
521namespace 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.
526using 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;
530using 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
535class Fail final {
536  repr::PtrLen &throw$;
537
538public:
539  Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
540  void operator()(const char *) noexcept;
541  void operator()(const std::string &) noexcept;
542};
543
544void Fail::operator()(const char *catch$) noexcept {
545  throw$ = cxxbridge1$exception(catch$, std::strlen(catch$));
546}
547
548void 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
556namespace {
557template <typename T>
558void destroy(T *ptr) {
559  ptr->~T();
560}
561} // namespace
562
563extern "C" {
564void cxxbridge1$unique_ptr$std$string$null(
565    std::unique_ptr<std::string> *ptr) noexcept {
566  new (ptr) std::unique_ptr<std::string>();
567}
568void 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}
572const std::string *cxxbridge1$unique_ptr$std$string$get(
573    const std::unique_ptr<std::string> &ptr) noexcept {
574  return ptr.get();
575}
576std::string *cxxbridge1$unique_ptr$std$string$release(
577    std::unique_ptr<std::string> &ptr) noexcept {
578  return ptr.release();
579}
580void cxxbridge1$unique_ptr$std$string$drop(
581    std::unique_ptr<std::string> *ptr) noexcept {
582  ptr->~unique_ptr();
583}
584} // extern "C"
585
586namespace {
587const std::size_t kMaxExpectedWordsInString = 8;
588static_assert(alignof(std::string) <= alignof(void *),
589              "unexpectedly large std::string alignment");
590static_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
782extern "C" {
783FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
784FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS)
785FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
786FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
787} // extern "C"
788
789namespace rust {
790inline namespace cxxbridge1 {
791FOR_EACH_RUST_VEC(RUST_VEC_OPS)
792} // namespace cxxbridge1
793} // namespace rust
794