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