diff --git a/include/cxx.h b/include/cxx.h index c02d3d94..1e336184 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -235,15 +235,25 @@ public: class const_iterator { public: + using difference_type = ptrdiff_t; using value_type = typename std::add_const::type; + using pointer = typename std::add_pointer< + typename std::add_const::type>::type; using reference = typename std::add_lvalue_reference< typename std::add_const::type>::type; + using iterator_category = std::forward_iterator_tag; const T &operator*() const { return *static_cast(this->pos); } + const T *operator->() const { return static_cast(this->pos); } const_iterator &operator++() { this->pos = static_cast(this->pos) + this->stride; return *this; } + const_iterator operator++(int) { + auto ret = const_iterator(*this); + this->pos = static_cast(this->pos) + this->stride; + return ret; + } bool operator==(const const_iterator &other) const { return this->pos == other.pos; } diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 69ef2b0c..01dc404e 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -53,7 +53,9 @@ pub mod ffi { fn c_take_ref_vector(v: &CxxVector); fn c_take_rust_vec(v: Vec); fn c_take_rust_vec_shared(v: Vec); + fn c_take_rust_vec_shared_forward_iterator(v: Vec); fn c_take_ref_rust_vec(v: &Vec); + fn c_take_ref_rust_vec_copy(v: &Vec); fn c_take_callback(callback: fn(String) -> usize); fn c_try_return_void() -> Result<()>; diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 79db42ce..2b5431fa 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -203,6 +203,18 @@ void c_take_rust_vec_shared(rust::Vec v) { } } +void c_take_rust_vec_shared_forward_iterator(rust::Vec v) { + // Exercise requirements of ForwardIterator + // https://en.cppreference.com/w/cpp/named_req/ForwardIterator + uint32_t sum = 0; + for (auto it = v.begin(), it_end = v.end(); it != it_end; it++) { + sum += it->z; + } + if (sum == 2021) { + cxx_test_suite_set_correct(); + } +} + void c_take_ref_rust_vec(const rust::Vec &v) { uint8_t sum = std::accumulate(v.begin(), v.end(), 0); if (sum == 200) { @@ -210,6 +222,18 @@ void c_take_ref_rust_vec(const rust::Vec &v) { } } +void c_take_ref_rust_vec_copy(const rust::Vec &v) { + // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the + // requirements for std::iterator_traits. + // https://en.cppreference.com/w/cpp/iterator/iterator_traits + std::vector cxx_v; + std::copy(v.begin(), v.end(), back_inserter(cxx_v)); + uint8_t sum = std::accumulate(cxx_v.begin(), cxx_v.end(), 0); + if (sum == 200) { + cxx_test_suite_set_correct(); + } +} + void c_take_callback(rust::Fn callback) { callback("2020"); } diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index 4600d643..da8ca564 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -57,7 +57,9 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr> v); void c_take_ref_vector(const std::vector &v); void c_take_rust_vec(rust::Vec v); void c_take_rust_vec_shared(rust::Vec v); +void c_take_rust_vec_shared_forward_iterator(rust::Vec v); void c_take_ref_rust_vec(const rust::Vec &v); +void c_take_ref_rust_vec_copy(const rust::Vec &v); void c_take_callback(rust::Fn callback); void c_try_return_void(); diff --git a/tests/test.rs b/tests/test.rs index 4fd52d35..d6850aac 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -94,14 +94,18 @@ fn test_c_take() { ffi::c_return_unique_ptr_vector_shared() )); check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8())); - check!(ffi::c_take_rust_vec([86_u8, 75_u8, 30_u8, 9_u8].to_vec())); + let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec(); + check!(ffi::c_take_rust_vec(test_vec.clone())); check!(ffi::c_take_rust_vec_shared(vec![ ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 } ])); - check!(ffi::c_take_ref_rust_vec( - &[86_u8, 75_u8, 30_u8, 9_u8].to_vec() - )); + check!(ffi::c_take_rust_vec_shared_forward_iterator(vec![ + ffi::Shared { z: 1010 }, + ffi::Shared { z: 1011 } + ])); + check!(ffi::c_take_ref_rust_vec(&test_vec)); + check!(ffi::c_take_ref_rust_vec_copy(&test_vec)); } #[test]