cpp_core/
iterator.rs

1use crate::ops::{Decrement, Increment, Indirection};
2use crate::{CppBox, CppDeletable, Ref};
3use std::os::raw::c_char;
4
5/// `Iterator` and `DoubleEndedIterator` backed by C++ iterators.
6///
7/// This object is produced by `IntoIterator` implementations on  pointer types
8/// (`&CppBox`, `&mut CppBox`, `Ptr`, `Ref`). You can also use
9/// `cpp_iter` function to construct it manually from two C++ iterator objects.
10pub struct CppIterator<T1, T2>
11where
12    T1: CppDeletable,
13    T2: CppDeletable,
14{
15    begin: CppBox<T1>,
16    end: CppBox<T2>,
17}
18
19/// Constructs a Rust-style iterator from C++ iterators pointing to begin and end
20/// of the collection.
21///
22/// ### Safety
23///
24/// `begin` and `end` must be valid. It's not possible to make any guarantees about safety, since
25/// `CppIterator` will call arbitrary C++ library code when used.
26pub unsafe fn cpp_iter<T1, T2>(begin: CppBox<T1>, end: CppBox<T2>) -> CppIterator<T1, T2>
27where
28    T1: CppDeletable,
29    T2: CppDeletable,
30{
31    CppIterator { begin, end }
32}
33
34impl<T1, T2> Iterator for CppIterator<T1, T2>
35where
36    T1: CppDeletable + PartialEq<Ref<T2>> + Indirection + Increment,
37    T2: CppDeletable,
38{
39    type Item = <T1 as Indirection>::Output;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        unsafe {
43            if self.begin == self.end.as_ref() {
44                None
45            } else {
46                let inner = &mut *self.begin.as_mut_raw_ptr();
47                let value = inner.indirection();
48                let inner = &mut *self.begin.as_mut_raw_ptr();
49                inner.inc();
50                Some(value)
51            }
52        }
53    }
54}
55
56impl<T1, T2> DoubleEndedIterator for CppIterator<T1, T2>
57where
58    T1: CppDeletable + PartialEq<Ref<T2>> + Indirection + Increment,
59    T2: CppDeletable + Decrement + Indirection<Output = <T1 as Indirection>::Output>,
60{
61    fn next_back(&mut self) -> Option<Self::Item> {
62        unsafe {
63            if self.begin == self.end.as_ref() {
64                None
65            } else {
66                let inner = &mut *self.end.as_mut_raw_ptr();
67                inner.dec();
68                let inner = &mut *self.end.as_mut_raw_ptr();
69                let value = inner.indirection();
70                Some(value)
71            }
72        }
73    }
74}
75
76/// A convenience trait that provides `end_ptr()` method for slices.
77pub trait EndPtr {
78    /// Type of item.
79    type Item;
80    /// Returns pointer to the end of the slice (past the last element).
81    fn end_ptr(&self) -> *const Self::Item;
82}
83
84impl<'a, T> EndPtr for &'a [T] {
85    type Item = T;
86    fn end_ptr(&self) -> *const T {
87        unsafe { self.as_ptr().add(self.len()) }
88    }
89}
90
91impl<'a> EndPtr for &'a str {
92    type Item = c_char;
93    fn end_ptr(&self) -> *const c_char {
94        unsafe { self.as_ptr().add(self.len()) as *const c_char }
95    }
96}