• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "tests/ffi/tests.h"
2 #include "tests/ffi/lib.rs.h"
3 #include <cstdlib>
4 #include <cstring>
5 #include <iterator>
6 #include <memory>
7 #include <numeric>
8 #include <stdexcept>
9 #include <string>
10 #include <tuple>
11 
12 extern "C" void cxx_test_suite_set_correct() noexcept;
13 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
14 extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
15 
16 namespace tests {
17 
18 static constexpr char SLICE_DATA[] = "2020";
19 
C(size_t n)20 C::C(size_t n) : n(n) {}
21 
get() const22 size_t C::get() const { return this->n; }
23 
get2() const24 size_t C::get2() const { return this->n; }
25 
getRef() const26 const size_t &C::getRef() const { return this->n; }
27 
getMut()28 size_t &C::getMut() { return this->n; }
29 
set(size_t n)30 size_t C::set(size_t n) {
31   this->n = n;
32   return this->n;
33 }
34 
set_succeed(size_t n)35 size_t C::set_succeed(size_t n) { return this->set(n); }
36 
get_fail()37 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
38 
c_method_on_shared() const39 size_t Shared::c_method_on_shared() const noexcept { return 2021; }
40 
c_method_ref_on_shared() const41 const size_t &Shared::c_method_ref_on_shared() const noexcept {
42   return this->z;
43 }
44 
c_method_mut_on_shared()45 size_t &Shared::c_method_mut_on_shared() noexcept { return this->z; }
46 
c_set_array(int32_t val)47 void Array::c_set_array(int32_t val) noexcept {
48   this->a = {val, val, val, val};
49 }
50 
get_v() const51 const std::vector<uint8_t> &C::get_v() const { return this->v; }
52 
get_v()53 std::vector<uint8_t> &C::get_v() { return this->v; }
54 
c_return_primitive()55 size_t c_return_primitive() { return 2020; }
56 
c_return_shared()57 Shared c_return_shared() { return Shared{2020}; }
58 
c_return_ns_shared()59 ::A::AShared c_return_ns_shared() { return ::A::AShared{2020}; }
60 
c_return_nested_ns_shared()61 ::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; }
62 
c_return_box()63 rust::Box<R> c_return_box() {
64   Shared shared{0};
65   rust::Box<Shared> box{shared}; // explicit constructor from const T&
66   rust::Box<Shared> other{std::move(shared)}; // explicit constructor from T&&
67   box = std::move(other);                     // move assignment
68   rust::Box<Shared> box2(*box);               // copy from another Box
69   rust::Box<Shared> other2(std::move(other)); // move constructor
70   rust::Box<Shared>::in_place(shared.z);      // placement static factory
71   rust::Box<Shared>::in_place<size_t>(0);
72   return rust::Box<R>::from_raw(cxx_test_suite_get_box());
73 }
74 
c_return_unique_ptr()75 std::unique_ptr<C> c_return_unique_ptr() {
76   return std::unique_ptr<C>(new C{2020});
77 }
78 
c_return_shared_ptr()79 std::shared_ptr<C> c_return_shared_ptr() {
80   return std::shared_ptr<C>(new C{2020});
81 }
82 
c_return_ns_unique_ptr()83 std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
84   return std::unique_ptr<::H::H>(new ::H::H{"hello"});
85 }
86 
c_return_ref(const Shared & shared)87 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
88 
c_return_ns_ref(const::A::AShared & shared)89 const size_t &c_return_ns_ref(const ::A::AShared &shared) {
90   return shared.type;
91 }
92 
c_return_nested_ns_ref(const::A::B::ABShared & shared)93 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) {
94   return shared.z;
95 }
96 
c_return_mut(Shared & shared)97 size_t &c_return_mut(Shared &shared) { return shared.z; }
98 
c_return_str(const Shared & shared)99 rust::Str c_return_str(const Shared &shared) {
100   (void)shared;
101   return "2020";
102 }
103 
c_return_slice_char(const Shared & shared)104 rust::Slice<const char> c_return_slice_char(const Shared &shared) {
105   (void)shared;
106   return rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA));
107 }
108 
c_return_mutsliceu8(rust::Slice<uint8_t> slice)109 rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
110   return slice;
111 }
112 
c_return_rust_string()113 rust::String c_return_rust_string() { return "2020"; }
114 
c_return_rust_string_lossy()115 rust::String c_return_rust_string_lossy() {
116   return rust::String::lossy("Hello \xf0\x90\x80World");
117 }
118 
c_return_unique_ptr_string()119 std::unique_ptr<std::string> c_return_unique_ptr_string() {
120   return std::unique_ptr<std::string>(new std::string("2020"));
121 }
122 
c_return_unique_ptr_vector_u8()123 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
124   auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
125   vec->push_back(86);
126   vec->push_back(75);
127   vec->push_back(30);
128   vec->push_back(9);
129   return vec;
130 }
131 
c_return_unique_ptr_vector_f64()132 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
133   auto vec = std::unique_ptr<std::vector<double>>(new std::vector<double>());
134   vec->push_back(86.0);
135   vec->push_back(75.0);
136   vec->push_back(30.0);
137   vec->push_back(9.5);
138   return vec;
139 }
140 
c_return_unique_ptr_vector_string()141 std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string() {
142   return std::unique_ptr<std::vector<std::string>>(
143       new std::vector<std::string>());
144 }
145 
c_return_unique_ptr_vector_shared()146 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
147   auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
148   vec->push_back(Shared{1010});
149   vec->push_back(Shared{1011});
150   return vec;
151 }
152 
c_return_unique_ptr_vector_opaque()153 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque() {
154   return std::unique_ptr<std::vector<C>>(new std::vector<C>());
155 }
156 
c_return_ref_vector(const C & c)157 const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
158   return c.get_v();
159 }
160 
c_return_mut_vector(C & c)161 std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); }
162 
c_return_rust_vec_u8()163 rust::Vec<uint8_t> c_return_rust_vec_u8() {
164   rust::Vec<uint8_t> vec{2, 0, 2, 0};
165   return vec;
166 }
167 
c_return_ref_rust_vec(const C & c)168 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
169   (void)c;
170   throw std::runtime_error("unimplemented");
171 }
172 
c_return_mut_rust_vec(C & c)173 rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
174   (void)c;
175   throw std::runtime_error("unimplemented");
176 }
177 
c_return_rust_vec_string()178 rust::Vec<rust::String> c_return_rust_vec_string() {
179   return {"2", "0", "2", "0"};
180 }
181 
c_return_rust_vec_bool()182 rust::Vec<bool> c_return_rust_vec_bool() { return {true, true, false}; }
183 
c_return_identity(size_t n)184 size_t c_return_identity(size_t n) { return n; }
185 
c_return_sum(size_t n1,size_t n2)186 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
187 
c_return_enum(uint16_t n)188 Enum c_return_enum(uint16_t n) {
189   if (n <= static_cast<uint16_t>(Enum::AVal)) {
190     return Enum::AVal;
191   } else if (n <= static_cast<uint16_t>(Enum::BVal)) {
192     return Enum::BVal;
193   } else {
194     return Enum::CVal;
195   }
196 }
197 
c_return_ns_enum(uint16_t n)198 ::A::AEnum c_return_ns_enum(uint16_t n) {
199   if (n <= static_cast<uint16_t>(::A::AEnum::AAVal)) {
200     return ::A::AEnum::AAVal;
201   } else if (n <= static_cast<uint16_t>(::A::AEnum::ABVal)) {
202     return ::A::AEnum::ABVal;
203   } else {
204     return ::A::AEnum::ACVal;
205   }
206 }
207 
c_return_nested_ns_enum(uint16_t n)208 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n) {
209   if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABAVal)) {
210     return ::A::B::ABEnum::ABAVal;
211   } else if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABBVal)) {
212     return ::A::B::ABEnum::ABBVal;
213   } else {
214     return ::A::B::ABEnum::ABCVal;
215   }
216 }
217 
c_return_const_ptr(size_t c)218 const C *c_return_const_ptr(size_t c) { return new C(c); }
219 
c_return_mut_ptr(size_t c)220 C *c_return_mut_ptr(size_t c) { return new C(c); }
221 
Borrow(const std::string & s)222 Borrow::Borrow(const std::string &s) : s(s) {}
223 
const_member() const224 void Borrow::const_member() const {}
225 
nonconst_member()226 void Borrow::nonconst_member() {}
227 
c_return_borrow(const std::string & s)228 std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
229   return std::unique_ptr<Borrow>(new Borrow(s));
230 }
231 
c_take_primitive(size_t n)232 void c_take_primitive(size_t n) {
233   if (n == 2020) {
234     cxx_test_suite_set_correct();
235   }
236 }
237 
c_take_shared(Shared shared)238 void c_take_shared(Shared shared) {
239   if (shared.z == 2020) {
240     cxx_test_suite_set_correct();
241   }
242 }
243 
c_take_ns_shared(::A::AShared shared)244 void c_take_ns_shared(::A::AShared shared) {
245   if (shared.type == 2020) {
246     cxx_test_suite_set_correct();
247   }
248 }
249 
c_take_nested_ns_shared(::A::B::ABShared shared)250 void c_take_nested_ns_shared(::A::B::ABShared shared) {
251   if (shared.z == 2020) {
252     cxx_test_suite_set_correct();
253   }
254 }
255 
c_take_box(rust::Box<R> r)256 void c_take_box(rust::Box<R> r) {
257   if (cxx_test_suite_r_is_correct(&*r)) {
258     cxx_test_suite_set_correct();
259   }
260 }
261 
c_take_unique_ptr(std::unique_ptr<C> c)262 void c_take_unique_ptr(std::unique_ptr<C> c) {
263   if (c->get() == 2020) {
264     cxx_test_suite_set_correct();
265   }
266 }
267 
c_take_ref_r(const R & r)268 void c_take_ref_r(const R &r) {
269   if (cxx_test_suite_r_is_correct(&r)) {
270     cxx_test_suite_set_correct();
271   }
272 }
273 
c_take_ref_c(const C & c)274 void c_take_ref_c(const C &c) {
275   if (c.get() == 2020) {
276     cxx_test_suite_set_correct();
277   }
278 }
279 
c_take_ref_ns_c(const::H::H & h)280 void c_take_ref_ns_c(const ::H::H &h) {
281   if (h.h == "hello") {
282     cxx_test_suite_set_correct();
283   }
284 }
285 
c_take_str(rust::Str s)286 void c_take_str(rust::Str s) {
287   if (std::string(s) == "2020") {
288     cxx_test_suite_set_correct();
289   }
290 }
291 
c_take_slice_char(rust::Slice<const char> s)292 void c_take_slice_char(rust::Slice<const char> s) {
293   if (std::string(s.data(), s.size()) == "2020") {
294     cxx_test_suite_set_correct();
295   }
296 }
297 
c_take_slice_shared(rust::Slice<const Shared> s)298 void c_take_slice_shared(rust::Slice<const Shared> s) {
299   if (s.size() == 2 && s.data()->z == 2020 && s[1].z == 2021 &&
300       s.at(1).z == 2021 && s.front().z == 2020 && s.back().z == 2021) {
301     cxx_test_suite_set_correct();
302   }
303 }
304 
c_take_slice_shared_sort(rust::Slice<Shared> s)305 void c_take_slice_shared_sort(rust::Slice<Shared> s) {
306   // Exercise requirements of RandomAccessIterator.
307   // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
308   std::sort(s.begin(), s.end());
309   if (s[0].z == 0 && s[1].z == 2 && s[2].z == 4 && s[3].z == 7) {
310     cxx_test_suite_set_correct();
311   }
312 }
313 
c_take_slice_r(rust::Slice<const R> s)314 void c_take_slice_r(rust::Slice<const R> s) {
315   if (s.size() == 3 && s[0].get() == 2020 && s[1].get() == 2050) {
316     cxx_test_suite_set_correct();
317   }
318 }
319 
operator <(const R & a,const R & b)320 bool operator<(const R &a, const R &b) noexcept { return a.get() < b.get(); }
321 
c_take_slice_r_sort(rust::Slice<R> s)322 void c_take_slice_r_sort(rust::Slice<R> s) {
323   std::qsort(s.data(), s.size(), rust::size_of<decltype(s)::value_type>(),
324              [](const void *fst, const void *snd) {
325                auto &a = *static_cast<const R *>(fst);
326                auto &b = *static_cast<const R *>(snd);
327                return a < b ? -1 : b < a ? 1 : 0;
328              });
329   if (s[0].get() == 2020 && s[1].get() == 2021 && s[2].get() == 2050) {
330     cxx_test_suite_set_correct();
331   }
332 }
333 
c_take_rust_string(rust::String s)334 void c_take_rust_string(rust::String s) {
335   if (std::string(s) == "2020") {
336     cxx_test_suite_set_correct();
337   }
338 }
339 
c_take_unique_ptr_string(std::unique_ptr<std::string> s)340 void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
341   if (*s == "2020") {
342     cxx_test_suite_set_correct();
343   }
344 }
345 
c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v)346 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v) {
347   if (v->size() == 3) {
348     cxx_test_suite_set_correct();
349   }
350 }
351 
c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v)352 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
353   if (v->size() == 5) {
354     cxx_test_suite_set_correct();
355   }
356 }
357 
c_take_unique_ptr_vector_string(std::unique_ptr<std::vector<std::string>> v)358 void c_take_unique_ptr_vector_string(
359     std::unique_ptr<std::vector<std::string>> v) {
360   (void)v;
361   cxx_test_suite_set_correct();
362 }
363 
c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v)364 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
365   if (v->size() == 3) {
366     cxx_test_suite_set_correct();
367   }
368 }
369 
c_take_ref_vector(const std::vector<uint8_t> & v)370 void c_take_ref_vector(const std::vector<uint8_t> &v) {
371   if (v.size() == 4) {
372     cxx_test_suite_set_correct();
373   }
374 }
375 
c_take_rust_vec(rust::Vec<uint8_t> v)376 void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
377 
c_take_rust_vec_index(rust::Vec<uint8_t> v)378 void c_take_rust_vec_index(rust::Vec<uint8_t> v) {
379   try {
380     v.at(100);
381   } catch (const std::out_of_range &ex) {
382     std::string expected = "rust::Vec index out of range";
383     if (ex.what() == expected) {
384       cxx_test_suite_set_correct();
385     }
386   }
387 }
388 
c_take_rust_vec_shared(rust::Vec<Shared> v)389 void c_take_rust_vec_shared(rust::Vec<Shared> v) {
390   uint32_t sum = 0;
391   for (auto i : v) {
392     sum += i.z;
393   }
394   if (sum == 2021) {
395     cxx_test_suite_set_correct();
396   }
397 }
398 
c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v)399 void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v) {
400   uint32_t sum = 0;
401   for (auto i : v) {
402     sum += i.type;
403   }
404   if (sum == 2021) {
405     cxx_test_suite_set_correct();
406   }
407 }
408 
c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v)409 void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v) {
410   uint32_t sum = 0;
411   for (auto i : v) {
412     sum += i.z;
413   }
414   if (sum == 2021) {
415     cxx_test_suite_set_correct();
416   }
417 }
418 
c_take_rust_vec_string(rust::Vec<rust::String> v)419 void c_take_rust_vec_string(rust::Vec<rust::String> v) {
420   (void)v;
421   cxx_test_suite_set_correct();
422 }
423 
c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v)424 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
425   // Exercise requirements of ForwardIterator
426   // https://en.cppreference.com/w/cpp/named_req/ForwardIterator
427   uint32_t sum = 0, csum = 0;
428   for (auto it = v.begin(), it_end = v.end(); it != it_end; it++) {
429     sum += it->z;
430   }
431   for (auto it = v.cbegin(), it_end = v.cend(); it != it_end; it++) {
432     csum += it->z;
433   }
434   if (sum == 2021 && csum == 2021) {
435     cxx_test_suite_set_correct();
436   }
437 }
438 
c_take_rust_vec_shared_sort(rust::Vec<Shared> v)439 void c_take_rust_vec_shared_sort(rust::Vec<Shared> v) {
440   // Exercise requirements of RandomAccessIterator.
441   // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
442   std::sort(v.begin(), v.end());
443   if (v[0].z == 0 && v[1].z == 2 && v[2].z == 4 && v[3].z == 7) {
444     cxx_test_suite_set_correct();
445   }
446 }
447 
c_take_rust_vec_shared_index(rust::Vec<Shared> v)448 void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
449   if (v[0].z == 1010 && v.at(0).z == 1010 && v.front().z == 1010 &&
450       v[1].z == 1011 && v.at(1).z == 1011 && v.back().z == 1011) {
451     cxx_test_suite_set_correct();
452   }
453 }
454 
c_take_rust_vec_shared_push(rust::Vec<Shared> v)455 void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
456   v.push_back(Shared{3});
457   v.emplace_back(Shared{2});
458   if (v[v.size() - 2].z == 3 && v.back().z == 2) {
459     cxx_test_suite_set_correct();
460   }
461 }
462 
c_take_rust_vec_shared_truncate(rust::Vec<Shared> v)463 void c_take_rust_vec_shared_truncate(rust::Vec<Shared> v) {
464   v.truncate(1);
465   if (v.size() == 1) {
466     v.truncate(0);
467     if (v.size() == 0) {
468       cxx_test_suite_set_correct();
469     }
470   }
471 }
472 
c_take_rust_vec_shared_clear(rust::Vec<Shared> v)473 void c_take_rust_vec_shared_clear(rust::Vec<Shared> v) {
474   v.clear();
475   if (v.size() == 0) {
476     cxx_test_suite_set_correct();
477   }
478 }
479 
c_take_ref_rust_vec(const rust::Vec<uint8_t> & v)480 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
481   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
482   if (sum == 200) {
483     cxx_test_suite_set_correct();
484   }
485 }
486 
c_take_ref_rust_vec_string(const rust::Vec<rust::String> & v)487 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
488   (void)v;
489   cxx_test_suite_set_correct();
490 }
491 
c_take_ref_rust_vec_index(const rust::Vec<uint8_t> & v)492 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
493   if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
494       v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
495     cxx_test_suite_set_correct();
496   }
497 }
498 
c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> & v)499 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
500   // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
501   // requirements for std::iterator_traits.
502   // https://en.cppreference.com/w/cpp/iterator/iterator_traits
503   std::vector<uint8_t> stdv;
504   std::copy(v.begin(), v.end(), std::back_inserter(stdv));
505   uint8_t sum = std::accumulate(stdv.begin(), stdv.end(), 0);
506   if (sum == 200) {
507     cxx_test_suite_set_correct();
508   }
509 }
510 
c_take_ref_shared_string(const SharedString & s)511 const SharedString &c_take_ref_shared_string(const SharedString &s) {
512   if (std::string(s.msg) == "2020") {
513     cxx_test_suite_set_correct();
514   }
515   return s;
516 }
517 
c_take_callback(rust::Fn<size_t (rust::String)> callback)518 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
519   callback("2020");
520 }
521 
c_take_callback_ref(rust::Fn<void (const rust::String &)> callback)522 void c_take_callback_ref(rust::Fn<void(const rust::String &)> callback) {
523   const rust::String string = "2020";
524   callback(string);
525 }
526 
c_take_callback_mut(rust::Fn<void (rust::String &)> callback)527 void c_take_callback_mut(rust::Fn<void(rust::String &)> callback) {
528   rust::String string = "2020";
529   callback(string);
530 }
531 
c_take_enum(Enum e)532 void c_take_enum(Enum e) {
533   if (e == Enum::AVal) {
534     cxx_test_suite_set_correct();
535   }
536 }
537 
c_take_ns_enum(::A::AEnum e)538 void c_take_ns_enum(::A::AEnum e) {
539   if (e == ::A::AEnum::AAVal) {
540     cxx_test_suite_set_correct();
541   }
542 }
543 
c_take_nested_ns_enum(::A::B::ABEnum e)544 void c_take_nested_ns_enum(::A::B::ABEnum e) {
545   if (e == ::A::B::ABEnum::ABAVal) {
546     cxx_test_suite_set_correct();
547   }
548 }
549 
c_take_const_ptr(const C * c)550 size_t c_take_const_ptr(const C *c) { return c->get(); }
551 
c_take_mut_ptr(C * c)552 size_t c_take_mut_ptr(C *c) {
553   size_t result = c->get();
554   delete c;
555   return result;
556 }
557 
c_try_return_void()558 void c_try_return_void() {}
559 
c_try_return_primitive()560 size_t c_try_return_primitive() { return 2020; }
561 
c_fail_return_primitive()562 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
563 
c_try_return_box()564 rust::Box<R> c_try_return_box() { return c_return_box(); }
565 
c_try_return_ref(const rust::String & s)566 const rust::String &c_try_return_ref(const rust::String &s) { return s; }
567 
c_try_return_str(rust::Str s)568 rust::Str c_try_return_str(rust::Str s) { return s; }
569 
c_try_return_sliceu8(rust::Slice<const uint8_t> s)570 rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
571   return s;
572 }
573 
c_try_return_mutsliceu8(rust::Slice<uint8_t> s)574 rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) {
575   return s;
576 }
577 
c_try_return_rust_string()578 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
579 
c_try_return_unique_ptr_string()580 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
581   return c_return_unique_ptr_string();
582 }
583 
c_try_return_rust_vec()584 rust::Vec<uint8_t> c_try_return_rust_vec() {
585   throw std::runtime_error("unimplemented");
586 }
587 
c_try_return_rust_vec_string()588 rust::Vec<rust::String> c_try_return_rust_vec_string() {
589   throw std::runtime_error("unimplemented");
590 }
591 
c_try_return_ref_rust_vec(const C & c)592 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
593   (void)c;
594   throw std::runtime_error("unimplemented");
595 }
596 
c_get_use_count(const std::weak_ptr<C> & weak)597 size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept {
598   return weak.use_count();
599 }
600 
cxx_test_suite_get_unique_ptr()601 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
602   return std::unique_ptr<C>(new C{2020}).release();
603 }
604 
605 extern "C" void
cxx_test_suite_get_shared_ptr(std::shared_ptr<C> * repr)606 cxx_test_suite_get_shared_ptr(std::shared_ptr<C> *repr) noexcept {
607   new (repr) std::shared_ptr<C>(new C{2020});
608 }
609 
cxx_test_suite_get_unique_ptr_string()610 extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
611   return std::unique_ptr<std::string>(new std::string("2020")).release();
612 }
613 
cOverloadedMethod(int32_t x) const614 rust::String C::cOverloadedMethod(int32_t x) const {
615   return rust::String(std::to_string(x));
616 }
617 
cOverloadedMethod(rust::Str x) const618 rust::String C::cOverloadedMethod(rust::Str x) const {
619   return rust::String(std::string(x));
620 }
621 
cOverloadedFunction(int x)622 rust::String cOverloadedFunction(int x) {
623   return rust::String(std::to_string(x));
624 }
625 
cOverloadedFunction(rust::Str x)626 rust::String cOverloadedFunction(rust::Str x) {
627   return rust::String(std::string(x));
628 }
629 
c_take_trivial_ptr(std::unique_ptr<D> d)630 void c_take_trivial_ptr(std::unique_ptr<D> d) {
631   if (d->d == 30) {
632     cxx_test_suite_set_correct();
633   }
634 }
635 
c_take_trivial_ref(const D & d)636 void c_take_trivial_ref(const D &d) {
637   if (d.d == 30) {
638     cxx_test_suite_set_correct();
639   }
640 }
641 
c_take_trivial_mut_ref(D & d)642 void c_take_trivial_mut_ref(D &d) { (void)d; }
643 
c_take_trivial_pin_ref(const D & d)644 void c_take_trivial_pin_ref(const D &d) { (void)d; }
645 
c_take_trivial_pin_mut_ref(D & d)646 void c_take_trivial_pin_mut_ref(D &d) { (void)d; }
647 
c_take_trivial_ref_method() const648 void D::c_take_trivial_ref_method() const {
649   if (d == 30) {
650     cxx_test_suite_set_correct();
651   }
652 }
653 
c_take_trivial_mut_ref_method()654 void D::c_take_trivial_mut_ref_method() {
655   if (d == 30) {
656     cxx_test_suite_set_correct();
657   }
658 }
659 
c_take_trivial(D d)660 void c_take_trivial(D d) {
661   if (d.d == 30) {
662     cxx_test_suite_set_correct();
663   }
664 }
665 
c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g)666 void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g) {
667   if (g->g == 30) {
668     cxx_test_suite_set_correct();
669   }
670 }
671 
c_take_trivial_ns_ref(const::G::G & g)672 void c_take_trivial_ns_ref(const ::G::G &g) {
673   if (g.g == 30) {
674     cxx_test_suite_set_correct();
675   }
676 }
677 
c_take_trivial_ns(::G::G g)678 void c_take_trivial_ns(::G::G g) {
679   if (g.g == 30) {
680     cxx_test_suite_set_correct();
681   }
682 }
683 
c_take_opaque_ptr(std::unique_ptr<E> e)684 void c_take_opaque_ptr(std::unique_ptr<E> e) {
685   if (e->e == 40) {
686     cxx_test_suite_set_correct();
687   }
688 }
689 
c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f)690 void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f) {
691   if (f->f == 40) {
692     cxx_test_suite_set_correct();
693   }
694 }
695 
c_take_opaque_ref(const E & e)696 void c_take_opaque_ref(const E &e) {
697   if (e.e == 40 && e.e_str == "hello") {
698     cxx_test_suite_set_correct();
699   }
700 }
701 
c_take_opaque_ref_method() const702 void E::c_take_opaque_ref_method() const {
703   if (e == 40 && e_str == "hello") {
704     cxx_test_suite_set_correct();
705   }
706 }
707 
c_take_opaque_mut_ref_method()708 void E::c_take_opaque_mut_ref_method() {
709   if (e == 40 && e_str == "hello") {
710     cxx_test_suite_set_correct();
711   }
712 }
713 
c_take_opaque_ns_ref(const::F::F & f)714 void c_take_opaque_ns_ref(const ::F::F &f) {
715   if (f.f == 40 && f.f_str == "hello") {
716     cxx_test_suite_set_correct();
717   }
718 }
719 
c_return_trivial_ptr()720 std::unique_ptr<D> c_return_trivial_ptr() {
721   auto d = std::unique_ptr<D>(new D());
722   d->d = 30;
723   return d;
724 }
725 
c_return_trivial()726 D c_return_trivial() {
727   D d;
728   d.d = 30;
729   return d;
730 }
731 
c_return_trivial_ns_ptr()732 std::unique_ptr<::G::G> c_return_trivial_ns_ptr() {
733   auto g = std::unique_ptr<::G::G>(new ::G::G());
734   g->g = 30;
735   return g;
736 }
737 
c_return_trivial_ns()738 ::G::G c_return_trivial_ns() {
739   ::G::G g;
740   g.g = 30;
741   return g;
742 }
743 
c_return_opaque_ptr()744 std::unique_ptr<E> c_return_opaque_ptr() {
745   auto e = std::unique_ptr<E>(new E());
746   e->e = 40;
747   e->e_str = std::string("hello");
748   return e;
749 }
750 
c_return_opaque_mut_pin(E & e)751 E &c_return_opaque_mut_pin(E &e) { return e; }
752 
c_return_ns_opaque_ptr()753 std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
754   auto f = std::unique_ptr<::F::F>(new ::F::F());
755   f->f = 40;
756   f->f_str = std::string("hello");
757   return f;
758 }
759 
cxx_run_test()760 extern "C" const char *cxx_run_test() noexcept {
761 #define STRINGIFY(x) #x
762 #define TOSTRING(x) STRINGIFY(x)
763 #define ASSERT(x)                                                              \
764   do {                                                                         \
765     if (!(x)) {                                                                \
766       return "Assertion failed: `" #x "`, " __FILE__ ":" TOSTRING(__LINE__);   \
767     }                                                                          \
768   } while (false)
769 
770   ASSERT(rust::size_of<R>() == sizeof(size_t));
771   ASSERT(rust::align_of<R>() == alignof(size_t));
772   ASSERT(rust::size_of<size_t>() == sizeof(size_t));
773   ASSERT(rust::align_of<size_t>() == alignof(size_t));
774 
775   ASSERT(r_return_primitive() == 2020);
776   ASSERT(r_return_shared().z == 2020);
777   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));
778   ASSERT(r_return_unique_ptr()->get() == 2020);
779   ASSERT(r_return_shared_ptr()->get() == 2020);
780   ASSERT(r_return_ref(Shared{2020}) == 2020);
781   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
782   ASSERT(std::string(r_return_rust_string()) == "2020");
783   ASSERT(*r_return_unique_ptr_string() == "2020");
784   ASSERT(r_return_identity(2020) == 2020);
785   ASSERT(r_return_sum(2020, 1) == 2021);
786   ASSERT(r_return_enum(0) == Enum::AVal);
787   ASSERT(r_return_enum(1) == Enum::BVal);
788   ASSERT(r_return_enum(2021) == Enum::CVal);
789 
790   r_take_primitive(2020);
791   r_take_shared(Shared{2020});
792   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
793   r_take_shared_ptr(std::shared_ptr<C>(new C{2020}));
794   r_take_ref_c(C{2020});
795   r_take_str(rust::Str("2020"));
796   r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
797   r_take_rust_string(rust::String("2020"));
798   r_take_unique_ptr_string(
799       std::unique_ptr<std::string>(new std::string("2020")));
800   r_take_ref_vector(std::vector<uint8_t>{20, 2, 0});
801   std::vector<uint64_t> empty_vector;
802   r_take_ref_empty_vector(empty_vector);
803   empty_vector.reserve(10);
804   r_take_ref_empty_vector(empty_vector);
805   r_take_enum(Enum::AVal);
806 
807   ASSERT(r_try_return_primitive() == 2020);
808   try {
809     r_fail_return_primitive();
810     ASSERT(false);
811   } catch (const rust::Error &e) {
812     ASSERT(std::strcmp(e.what(), "rust error") == 0);
813   }
814 
815   auto r = r_return_box();
816   ASSERT(r->get() == 2020);
817   ASSERT(r->set(2021) == 2021);
818   ASSERT(r->get() == 2021);
819 
820   using std::swap;
821   auto r2 = r_return_box();
822   swap(r, r2);
823   ASSERT(r->get() == 2020);
824   ASSERT(r2->get() == 2021);
825 
826   ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
827 
828   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
829 
830   ASSERT(Shared{1} == Shared{1});
831   ASSERT(Shared{1} != Shared{2});
832 
833   rust::String first = "first", second = "second", sec = "sec";
834   bool (rust::String::*cmp)(const rust::String &) const;
835   bool first_first, first_second, sec_second, second_sec;
836   for (auto test : {
837            std::tuple<decltype(cmp), bool, bool, bool, bool>{
838                &rust::String::operator==, true, false, false, false},
839            {&rust::String::operator!=, false, true, true, true},
840            {&rust::String::operator<, false, true, true, false},
841            {&rust::String::operator<=, true, true, true, false},
842            {&rust::String::operator>, false, false, false, true},
843            {&rust::String::operator>=, true, false, false, true},
844        }) {
845     std::tie(cmp, first_first, first_second, sec_second, second_sec) = test;
846     ASSERT((first.*cmp)(first) == first_first);
847     ASSERT((first.*cmp)(second) == first_second);
848     ASSERT((sec.*cmp)(second) == sec_second);
849     ASSERT((second.*cmp)(sec) == second_sec);
850   }
851 
852   rust::String cstring = "test";
853   ASSERT(cstring.length() == 4);
854   ASSERT(strncmp(cstring.data(), "test", 4) == 0);
855   ASSERT(strncmp(cstring.c_str(), "test", 5) == 0);
856   ASSERT(cstring.length() == 4);
857 
858   rust::String other_cstring = "foo";
859   swap(cstring, other_cstring);
860   ASSERT(cstring == "foo");
861   ASSERT(other_cstring == "test");
862 
863   ASSERT(cstring.capacity() == 3);
864   cstring.reserve(2);
865   ASSERT(cstring.capacity() == 3);
866   cstring.reserve(5);
867   ASSERT(cstring.capacity() >= 5);
868 
869   rust::Str cstr = "test";
870   rust::Str other_cstr = "foo";
871   swap(cstr, other_cstr);
872   ASSERT(cstr == "foo");
873   ASSERT(other_cstr == "test");
874 
875   const char *utf8_literal = u8"Test string";
876   const char16_t *utf16_literal = u"Test string";
877   rust::String utf8_rstring = utf8_literal;
878   rust::String utf16_rstring = utf16_literal;
879   ASSERT(utf8_rstring == utf16_rstring);
880 
881   const char *bad_utf8_literal = "test\x80";
882   const char16_t *bad_utf16_literal = u"test\xDD1E";
883   rust::String bad_utf8_rstring = rust::String::lossy(bad_utf8_literal);
884   rust::String bad_utf16_rstring = rust::String::lossy(bad_utf16_literal);
885   ASSERT(bad_utf8_rstring == bad_utf16_rstring);
886 
887   rust::Vec<int> vec1{1, 2};
888   rust::Vec<int> vec2{3, 4};
889   swap(vec1, vec2);
890   ASSERT(vec1[0] == 3 && vec1[1] == 4);
891   ASSERT(vec2[0] == 1 && vec2[1] == 2);
892 
893   // Test Vec<usize> and Vec<isize>. These are weird because on Linux and
894   // Windows size_t is exactly the same C++ type as one of the sized integer
895   // types (typically uint64_t, both of which are defined as unsigned long),
896   // while on macOS it is a distinct type.
897   // https://github.com/dtolnay/cxx/issues/705
898   (void)rust::Vec<size_t>();
899   (void)rust::Vec<rust::isize>();
900 
901   cxx_test_suite_set_correct();
902   return nullptr;
903 }
904 
905 } // namespace tests
906 
907 namespace other {
ns_c_take_trivial(::tests::D d)908 void ns_c_take_trivial(::tests::D d) {
909   if (d.d == 30) {
910     cxx_test_suite_set_correct();
911   }
912 }
913 
ns_c_return_trivial()914 ::tests::D ns_c_return_trivial() {
915   ::tests::D d;
916   d.d = 30;
917   return d;
918 }
919 
ns_c_take_ns_shared(::A::AShared shared)920 void ns_c_take_ns_shared(::A::AShared shared) {
921   if (shared.type == 2020) {
922     cxx_test_suite_set_correct();
923   }
924 }
925 } // namespace other
926 
927 namespace I {
get() const928 uint32_t I::get() const { return a; }
929 
ns_c_return_unique_ptr_ns()930 std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
931   return std::unique_ptr<I>(new I());
932 }
933 } // namespace I
934 
935 // Instantiate any remaining class member functions not already covered above.
936 // This is an easy way to at least typecheck anything missed by unit tests.
937 // https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation
938 // > When an explicit instantiation names a class template specialization, it
939 // > serves as an explicit instantiation of the same kind (declaration or
940 // > definition) of each of its non-inherited non-template members that has not
941 // > been previously explicitly specialized in the translation unit.
942 #if defined(CXX_TEST_INSTANTIATIONS)
943 template class rust::Box<tests::Shared>;
944 template class rust::Slice<const char>;
945 template class rust::Slice<const uint8_t>;
946 template class rust::Slice<uint8_t>;
947 template class rust::Slice<const tests::Shared>;
948 template class rust::Slice<tests::Shared>;
949 template class rust::Slice<const tests::R>;
950 template class rust::Slice<tests::R>;
951 template class rust::Vec<uint8_t>;
952 template class rust::Vec<rust::String>;
953 template class rust::Vec<tests::Shared>;
954 template class rust::Fn<size_t(rust::String)>;
955 #endif
956