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 12extern "C" void cxx_test_suite_set_correct() noexcept; 13extern "C" tests::R *cxx_test_suite_get_box() noexcept; 14extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept; 15 16namespace tests { 17 18static constexpr char SLICE_DATA[] = "2020"; 19 20C::C(size_t n) : n(n) {} 21 22size_t C::get() const { return this->n; } 23 24size_t C::get2() const { return this->n; } 25 26const size_t &C::getRef() const { return this->n; } 27 28size_t &C::getMut() { return this->n; } 29 30size_t C::set(size_t n) { 31 this->n = n; 32 return this->n; 33} 34 35size_t C::set_succeed(size_t n) { return this->set(n); } 36 37size_t C::get_fail() { throw std::runtime_error("unimplemented"); } 38 39size_t Shared::c_method_on_shared() const noexcept { return 2021; } 40 41const size_t &Shared::c_method_ref_on_shared() const noexcept { 42 return this->z; 43} 44 45size_t &Shared::c_method_mut_on_shared() noexcept { return this->z; } 46 47void Array::c_set_array(int32_t val) noexcept { 48 this->a = {val, val, val, val}; 49} 50 51const std::vector<uint8_t> &C::get_v() const { return this->v; } 52 53std::vector<uint8_t> &C::get_v() { return this->v; } 54 55size_t c_return_primitive() { return 2020; } 56 57Shared c_return_shared() { return Shared{2020}; } 58 59::A::AShared c_return_ns_shared() { return ::A::AShared{2020}; } 60 61::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; } 62 63rust::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 75std::unique_ptr<C> c_return_unique_ptr() { 76 return std::unique_ptr<C>(new C{2020}); 77} 78 79std::shared_ptr<C> c_return_shared_ptr() { 80 return std::shared_ptr<C>(new C{2020}); 81} 82 83std::unique_ptr<::H::H> c_return_ns_unique_ptr() { 84 return std::unique_ptr<::H::H>(new ::H::H{"hello"}); 85} 86 87const size_t &c_return_ref(const Shared &shared) { return shared.z; } 88 89const size_t &c_return_ns_ref(const ::A::AShared &shared) { 90 return shared.type; 91} 92 93const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { 94 return shared.z; 95} 96 97size_t &c_return_mut(Shared &shared) { return shared.z; } 98 99rust::Str c_return_str(const Shared &shared) { 100 (void)shared; 101 return "2020"; 102} 103 104rust::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 109rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) { 110 return slice; 111} 112 113rust::String c_return_rust_string() { return "2020"; } 114 115rust::String c_return_rust_string_lossy() { 116 return rust::String::lossy("Hello \xf0\x90\x80World"); 117} 118 119std::unique_ptr<std::string> c_return_unique_ptr_string() { 120 return std::unique_ptr<std::string>(new std::string("2020")); 121} 122 123std::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 132std::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 141std::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 146std::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 153std::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 157const std::vector<uint8_t> &c_return_ref_vector(const C &c) { 158 return c.get_v(); 159} 160 161std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); } 162 163rust::Vec<uint8_t> c_return_rust_vec_u8() { 164 rust::Vec<uint8_t> vec{2, 0, 2, 0}; 165 return vec; 166} 167 168const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) { 169 (void)c; 170 throw std::runtime_error("unimplemented"); 171} 172 173rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) { 174 (void)c; 175 throw std::runtime_error("unimplemented"); 176} 177 178rust::Vec<rust::String> c_return_rust_vec_string() { 179 return {"2", "0", "2", "0"}; 180} 181 182rust::Vec<bool> c_return_rust_vec_bool() { return {true, true, false}; } 183 184size_t c_return_identity(size_t n) { return n; } 185 186size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; } 187 188Enum 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 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 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 218const C *c_return_const_ptr(size_t c) { return new C(c); } 219 220C *c_return_mut_ptr(size_t c) { return new C(c); } 221 222Borrow::Borrow(const std::string &s) : s(s) {} 223 224void Borrow::const_member() const {} 225 226void Borrow::nonconst_member() {} 227 228std::unique_ptr<Borrow> c_return_borrow(const std::string &s) { 229 return std::unique_ptr<Borrow>(new Borrow(s)); 230} 231 232void c_take_primitive(size_t n) { 233 if (n == 2020) { 234 cxx_test_suite_set_correct(); 235 } 236} 237 238void c_take_shared(Shared shared) { 239 if (shared.z == 2020) { 240 cxx_test_suite_set_correct(); 241 } 242} 243 244void c_take_ns_shared(::A::AShared shared) { 245 if (shared.type == 2020) { 246 cxx_test_suite_set_correct(); 247 } 248} 249 250void c_take_nested_ns_shared(::A::B::ABShared shared) { 251 if (shared.z == 2020) { 252 cxx_test_suite_set_correct(); 253 } 254} 255 256void 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 262void c_take_unique_ptr(std::unique_ptr<C> c) { 263 if (c->get() == 2020) { 264 cxx_test_suite_set_correct(); 265 } 266} 267 268void 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 274void c_take_ref_c(const C &c) { 275 if (c.get() == 2020) { 276 cxx_test_suite_set_correct(); 277 } 278} 279 280void c_take_ref_ns_c(const ::H::H &h) { 281 if (h.h == "hello") { 282 cxx_test_suite_set_correct(); 283 } 284} 285 286void c_take_str(rust::Str s) { 287 if (std::string(s) == "2020") { 288 cxx_test_suite_set_correct(); 289 } 290} 291 292void 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 298void 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 305void 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 314void 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 320bool operator<(const R &a, const R &b) noexcept { return a.get() < b.get(); } 321 322void 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 334void c_take_rust_string(rust::String s) { 335 if (std::string(s) == "2020") { 336 cxx_test_suite_set_correct(); 337 } 338} 339 340void c_take_unique_ptr_string(std::unique_ptr<std::string> s) { 341 if (*s == "2020") { 342 cxx_test_suite_set_correct(); 343 } 344} 345 346void 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 352void 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 358void 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 364void 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 370void c_take_ref_vector(const std::vector<uint8_t> &v) { 371 if (v.size() == 4) { 372 cxx_test_suite_set_correct(); 373 } 374} 375 376void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); } 377 378void 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 389void 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 399void 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 409void 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 419void c_take_rust_vec_string(rust::Vec<rust::String> v) { 420 (void)v; 421 cxx_test_suite_set_correct(); 422} 423 424void 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 439void 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 448void 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 455void 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 463void 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 473void 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 480void 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 487void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) { 488 (void)v; 489 cxx_test_suite_set_correct(); 490} 491 492void 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 499void 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 511const 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 518void c_take_callback(rust::Fn<size_t(rust::String)> callback) { 519 callback("2020"); 520} 521 522void c_take_callback_ref(rust::Fn<void(const rust::String &)> callback) { 523 const rust::String string = "2020"; 524 callback(string); 525} 526 527void c_take_callback_mut(rust::Fn<void(rust::String &)> callback) { 528 rust::String string = "2020"; 529 callback(string); 530} 531 532void c_take_enum(Enum e) { 533 if (e == Enum::AVal) { 534 cxx_test_suite_set_correct(); 535 } 536} 537 538void c_take_ns_enum(::A::AEnum e) { 539 if (e == ::A::AEnum::AAVal) { 540 cxx_test_suite_set_correct(); 541 } 542} 543 544void 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 550size_t c_take_const_ptr(const C *c) { return c->get(); } 551 552size_t c_take_mut_ptr(C *c) { 553 size_t result = c->get(); 554 delete c; 555 return result; 556} 557 558void c_try_return_void() {} 559 560size_t c_try_return_primitive() { return 2020; } 561 562size_t c_fail_return_primitive() { throw std::logic_error("logic error"); } 563 564rust::Box<R> c_try_return_box() { return c_return_box(); } 565 566const rust::String &c_try_return_ref(const rust::String &s) { return s; } 567 568rust::Str c_try_return_str(rust::Str s) { return s; } 569 570rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) { 571 return s; 572} 573 574rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) { 575 return s; 576} 577 578rust::String c_try_return_rust_string() { return c_return_rust_string(); } 579 580std::unique_ptr<std::string> c_try_return_unique_ptr_string() { 581 return c_return_unique_ptr_string(); 582} 583 584rust::Vec<uint8_t> c_try_return_rust_vec() { 585 throw std::runtime_error("unimplemented"); 586} 587 588rust::Vec<rust::String> c_try_return_rust_vec_string() { 589 throw std::runtime_error("unimplemented"); 590} 591 592const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) { 593 (void)c; 594 throw std::runtime_error("unimplemented"); 595} 596 597size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept { 598 return weak.use_count(); 599} 600 601extern "C" C *cxx_test_suite_get_unique_ptr() noexcept { 602 return std::unique_ptr<C>(new C{2020}).release(); 603} 604 605extern "C" void 606cxx_test_suite_get_shared_ptr(std::shared_ptr<C> *repr) noexcept { 607 new (repr) std::shared_ptr<C>(new C{2020}); 608} 609 610extern "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 614rust::String C::cOverloadedMethod(int32_t x) const { 615 return rust::String(std::to_string(x)); 616} 617 618rust::String C::cOverloadedMethod(rust::Str x) const { 619 return rust::String(std::string(x)); 620} 621 622rust::String cOverloadedFunction(int x) { 623 return rust::String(std::to_string(x)); 624} 625 626rust::String cOverloadedFunction(rust::Str x) { 627 return rust::String(std::string(x)); 628} 629 630void c_take_trivial_ptr(std::unique_ptr<D> d) { 631 if (d->d == 30) { 632 cxx_test_suite_set_correct(); 633 } 634} 635 636void c_take_trivial_ref(const D &d) { 637 if (d.d == 30) { 638 cxx_test_suite_set_correct(); 639 } 640} 641 642void c_take_trivial_mut_ref(D &d) { (void)d; } 643 644void c_take_trivial_pin_ref(const D &d) { (void)d; } 645 646void c_take_trivial_pin_mut_ref(D &d) { (void)d; } 647 648void D::c_take_trivial_ref_method() const { 649 if (d == 30) { 650 cxx_test_suite_set_correct(); 651 } 652} 653 654void D::c_take_trivial_mut_ref_method() { 655 if (d == 30) { 656 cxx_test_suite_set_correct(); 657 } 658} 659 660void c_take_trivial(D d) { 661 if (d.d == 30) { 662 cxx_test_suite_set_correct(); 663 } 664} 665 666void 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 672void c_take_trivial_ns_ref(const ::G::G &g) { 673 if (g.g == 30) { 674 cxx_test_suite_set_correct(); 675 } 676} 677 678void c_take_trivial_ns(::G::G g) { 679 if (g.g == 30) { 680 cxx_test_suite_set_correct(); 681 } 682} 683 684void c_take_opaque_ptr(std::unique_ptr<E> e) { 685 if (e->e == 40) { 686 cxx_test_suite_set_correct(); 687 } 688} 689 690void 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 696void 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 702void E::c_take_opaque_ref_method() const { 703 if (e == 40 && e_str == "hello") { 704 cxx_test_suite_set_correct(); 705 } 706} 707 708void E::c_take_opaque_mut_ref_method() { 709 if (e == 40 && e_str == "hello") { 710 cxx_test_suite_set_correct(); 711 } 712} 713 714void 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 720std::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 726D c_return_trivial() { 727 D d; 728 d.d = 30; 729 return d; 730} 731 732std::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 738::G::G c_return_trivial_ns() { 739 ::G::G g; 740 g.g = 30; 741 return g; 742} 743 744std::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 751E &c_return_opaque_mut_pin(E &e) { return e; } 752 753std::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 760extern "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 907namespace other { 908void ns_c_take_trivial(::tests::D d) { 909 if (d.d == 30) { 910 cxx_test_suite_set_correct(); 911 } 912} 913 914::tests::D ns_c_return_trivial() { 915 ::tests::D d; 916 d.d = 30; 917 return d; 918} 919 920void 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 927namespace I { 928uint32_t I::get() const { return a; } 929 930std::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) 943template class rust::Box<tests::Shared>; 944template class rust::Slice<const char>; 945template class rust::Slice<const uint8_t>; 946template class rust::Slice<uint8_t>; 947template class rust::Slice<const tests::Shared>; 948template class rust::Slice<tests::Shared>; 949template class rust::Slice<const tests::R>; 950template class rust::Slice<tests::R>; 951template class rust::Vec<uint8_t>; 952template class rust::Vec<rust::String>; 953template class rust::Vec<tests::Shared>; 954template class rust::Fn<size_t(rust::String)>; 955#endif 956