• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Less used details of `CxxVector` are exposed in this module. `CxxVector`
2 //! itself is exposed at the crate root.
3 
4 use crate::extern_type::ExternType;
5 use crate::kind::Trivial;
6 use crate::string::CxxString;
7 use core::ffi::c_void;
8 use core::fmt::{self, Debug};
9 use core::iter::FusedIterator;
10 use core::marker::{PhantomData, PhantomPinned};
11 use core::mem;
12 use core::pin::Pin;
13 use core::ptr;
14 use core::slice;
15 
16 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
17 ///
18 /// # Invariants
19 ///
20 /// As an invariant of this API and the static analysis of the cxx::bridge
21 /// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in
22 /// Rust code we will only ever look at a vector behind a reference or smart
23 /// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`.
24 #[repr(C, packed)]
25 pub struct CxxVector<T> {
26     _private: [T; 0],
27     _pinned: PhantomData<PhantomPinned>,
28 }
29 
30 impl<T> CxxVector<T>
31 where
32     T: VectorElement,
33 {
34     /// Returns the number of elements in the vector.
35     ///
36     /// Matches the behavior of C++ [std::vector\<T\>::size][size].
37     ///
38     /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
len(&self) -> usize39     pub fn len(&self) -> usize {
40         T::__vector_size(self)
41     }
42 
43     /// Returns true if the vector contains no elements.
44     ///
45     /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
46     ///
47     /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
is_empty(&self) -> bool48     pub fn is_empty(&self) -> bool {
49         self.len() == 0
50     }
51 
52     /// Returns a reference to an element at the given position, or `None` if
53     /// out of bounds.
get(&self, pos: usize) -> Option<&T>54     pub fn get(&self, pos: usize) -> Option<&T> {
55         if pos < self.len() {
56             Some(unsafe { self.get_unchecked(pos) })
57         } else {
58             None
59         }
60     }
61 
62     /// Returns a pinned mutable reference to an element at the given position,
63     /// or `None` if out of bounds.
index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>>64     pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
65         if pos < self.len() {
66             Some(unsafe { self.index_unchecked_mut(pos) })
67         } else {
68             None
69         }
70     }
71 
72     /// Returns a reference to an element without doing bounds checking.
73     ///
74     /// This is generally not recommended, use with caution! Calling this method
75     /// with an out-of-bounds index is undefined behavior even if the resulting
76     /// reference is not used.
77     ///
78     /// Matches the behavior of C++
79     /// [std::vector\<T\>::operator\[\] const][operator_at].
80     ///
81     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
get_unchecked(&self, pos: usize) -> &T82     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
83         let this = self as *const CxxVector<T> as *mut CxxVector<T>;
84         let ptr = T::__get_unchecked(this, pos) as *const T;
85         &*ptr
86     }
87 
88     /// Returns a pinned mutable reference to an element without doing bounds
89     /// checking.
90     ///
91     /// This is generally not recommended, use with caution! Calling this method
92     /// with an out-of-bounds index is undefined behavior even if the resulting
93     /// reference is not used.
94     ///
95     /// Matches the behavior of C++
96     /// [std::vector\<T\>::operator\[\]][operator_at].
97     ///
98     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T>99     pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
100         let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos);
101         Pin::new_unchecked(&mut *ptr)
102     }
103 
104     /// Returns a slice to the underlying contiguous array of elements.
as_slice(&self) -> &[T] where T: ExternType<Kind = Trivial>,105     pub fn as_slice(&self) -> &[T]
106     where
107         T: ExternType<Kind = Trivial>,
108     {
109         let len = self.len();
110         if len == 0 {
111             // The slice::from_raw_parts in the other branch requires a nonnull
112             // and properly aligned data ptr. C++ standard does not guarantee
113             // that data() on a vector with size 0 would return a nonnull
114             // pointer or sufficiently aligned pointer, so using it would be
115             // undefined behavior. Create our own empty slice in Rust instead
116             // which upholds the invariants.
117             &[]
118         } else {
119             let this = self as *const CxxVector<T> as *mut CxxVector<T>;
120             let ptr = unsafe { T::__get_unchecked(this, 0) };
121             unsafe { slice::from_raw_parts(ptr, len) }
122         }
123     }
124 
125     /// Returns a slice to the underlying contiguous array of elements by
126     /// mutable reference.
as_mut_slice(self: Pin<&mut Self>) -> &mut [T] where T: ExternType<Kind = Trivial>,127     pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
128     where
129         T: ExternType<Kind = Trivial>,
130     {
131         let len = self.len();
132         if len == 0 {
133             &mut []
134         } else {
135             let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) };
136             unsafe { slice::from_raw_parts_mut(ptr, len) }
137         }
138     }
139 
140     /// Returns an iterator over elements of type `&T`.
iter(&self) -> Iter<T>141     pub fn iter(&self) -> Iter<T> {
142         Iter { v: self, index: 0 }
143     }
144 
145     /// Returns an iterator over elements of type `Pin<&mut T>`.
iter_mut(self: Pin<&mut Self>) -> IterMut<T>146     pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
147         IterMut { v: self, index: 0 }
148     }
149 }
150 
151 /// Iterator over elements of a `CxxVector` by shared reference.
152 ///
153 /// The iterator element type is `&'a T`.
154 pub struct Iter<'a, T> {
155     v: &'a CxxVector<T>,
156     index: usize,
157 }
158 
159 impl<'a, T> IntoIterator for &'a CxxVector<T>
160 where
161     T: VectorElement,
162 {
163     type Item = &'a T;
164     type IntoIter = Iter<'a, T>;
165 
into_iter(self) -> Self::IntoIter166     fn into_iter(self) -> Self::IntoIter {
167         self.iter()
168     }
169 }
170 
171 impl<'a, T> Iterator for Iter<'a, T>
172 where
173     T: VectorElement,
174 {
175     type Item = &'a T;
176 
next(&mut self) -> Option<Self::Item>177     fn next(&mut self) -> Option<Self::Item> {
178         let next = self.v.get(self.index)?;
179         self.index += 1;
180         Some(next)
181     }
182 
size_hint(&self) -> (usize, Option<usize>)183     fn size_hint(&self) -> (usize, Option<usize>) {
184         let len = self.len();
185         (len, Some(len))
186     }
187 }
188 
189 impl<'a, T> ExactSizeIterator for Iter<'a, T>
190 where
191     T: VectorElement,
192 {
len(&self) -> usize193     fn len(&self) -> usize {
194         self.v.len() - self.index
195     }
196 }
197 
198 impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
199 
200 /// Iterator over elements of a `CxxVector` by pinned mutable reference.
201 ///
202 /// The iterator element type is `Pin<&'a mut T>`.
203 pub struct IterMut<'a, T> {
204     v: Pin<&'a mut CxxVector<T>>,
205     index: usize,
206 }
207 
208 impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>>
209 where
210     T: VectorElement,
211 {
212     type Item = Pin<&'a mut T>;
213     type IntoIter = IterMut<'a, T>;
214 
into_iter(self) -> Self::IntoIter215     fn into_iter(self) -> Self::IntoIter {
216         self.iter_mut()
217     }
218 }
219 
220 impl<'a, T> Iterator for IterMut<'a, T>
221 where
222     T: VectorElement,
223 {
224     type Item = Pin<&'a mut T>;
225 
next(&mut self) -> Option<Self::Item>226     fn next(&mut self) -> Option<Self::Item> {
227         let next = self.v.as_mut().index_mut(self.index)?;
228         self.index += 1;
229         // Extend lifetime to allow simultaneous holding of nonoverlapping
230         // elements, analogous to slice::split_first_mut.
231         unsafe {
232             let ptr = Pin::into_inner_unchecked(next) as *mut T;
233             Some(Pin::new_unchecked(&mut *ptr))
234         }
235     }
236 
size_hint(&self) -> (usize, Option<usize>)237     fn size_hint(&self) -> (usize, Option<usize>) {
238         let len = self.len();
239         (len, Some(len))
240     }
241 }
242 
243 impl<'a, T> ExactSizeIterator for IterMut<'a, T>
244 where
245     T: VectorElement,
246 {
len(&self) -> usize247     fn len(&self) -> usize {
248         self.v.len() - self.index
249     }
250 }
251 
252 impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
253 
254 impl<T> Debug for CxxVector<T>
255 where
256     T: VectorElement + Debug,
257 {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result258     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
259         formatter.debug_list().entries(self).finish()
260     }
261 }
262 
263 /// Trait bound for types which may be used as the `T` inside of a
264 /// `CxxVector<T>` in generic code.
265 ///
266 /// This trait has no publicly callable or implementable methods. Implementing
267 /// it outside of the CXX codebase is not supported.
268 ///
269 /// # Example
270 ///
271 /// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
272 /// in generic code.
273 ///
274 /// ```
275 /// use cxx::vector::{CxxVector, VectorElement};
276 /// use std::fmt::Display;
277 ///
278 /// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
279 /// where
280 ///     T: VectorElement + Display,
281 /// {
282 ///     println!("the vector elements are:");
283 ///     for element in vector {
284 ///         println!("  • {}", element);
285 ///     }
286 /// }
287 /// ```
288 ///
289 /// Writing the same generic function without a `VectorElement` trait bound
290 /// would not compile.
291 pub unsafe trait VectorElement: Sized {
292     #[doc(hidden)]
__typename(f: &mut fmt::Formatter) -> fmt::Result293     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
294     #[doc(hidden)]
__vector_size(v: &CxxVector<Self>) -> usize295     fn __vector_size(v: &CxxVector<Self>) -> usize;
296     #[doc(hidden)]
__get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self297     unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
298     #[doc(hidden)]
__unique_ptr_null() -> *mut c_void299     fn __unique_ptr_null() -> *mut c_void;
300     #[doc(hidden)]
__unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void301     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
302     #[doc(hidden)]
__unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>303     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
304     #[doc(hidden)]
__unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>305     unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
306     #[doc(hidden)]
__unique_ptr_drop(repr: *mut c_void)307     unsafe fn __unique_ptr_drop(repr: *mut c_void);
308 }
309 
310 macro_rules! impl_vector_element {
311     ($segment:expr, $name:expr, $ty:ty) => {
312         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
313 
314         unsafe impl VectorElement for $ty {
315             #[doc(hidden)]
316             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
317                 f.write_str($name)
318             }
319             #[doc(hidden)]
320             fn __vector_size(v: &CxxVector<$ty>) -> usize {
321                 extern "C" {
322                     attr! {
323                         #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
324                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
325                     }
326                 }
327                 unsafe { __vector_size(v) }
328             }
329             #[doc(hidden)]
330             unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
331                 extern "C" {
332                     attr! {
333                         #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
334                         fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
335                     }
336                 }
337                 __get_unchecked(v, pos)
338             }
339             #[doc(hidden)]
340             fn __unique_ptr_null() -> *mut c_void {
341                 extern "C" {
342                     attr! {
343                         #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
344                         fn __unique_ptr_null(this: *mut *mut c_void);
345                     }
346                 }
347                 let mut repr = ptr::null_mut::<c_void>();
348                 unsafe { __unique_ptr_null(&mut repr) }
349                 repr
350             }
351             #[doc(hidden)]
352             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
353                 extern "C" {
354                     attr! {
355                         #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
356                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
357                     }
358                 }
359                 let mut repr = ptr::null_mut::<c_void>();
360                 __unique_ptr_raw(&mut repr, raw);
361                 repr
362             }
363             #[doc(hidden)]
364             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
365                 extern "C" {
366                     attr! {
367                         #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
368                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
369                     }
370                 }
371                 __unique_ptr_get(&repr)
372             }
373             #[doc(hidden)]
374             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
375                 extern "C" {
376                     attr! {
377                         #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
378                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
379                     }
380                 }
381                 __unique_ptr_release(&mut repr)
382             }
383             #[doc(hidden)]
384             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
385                 extern "C" {
386                     attr! {
387                         #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
388                         fn __unique_ptr_drop(this: *mut *mut c_void);
389                     }
390                 }
391                 __unique_ptr_drop(&mut repr);
392             }
393         }
394     };
395 }
396 
397 macro_rules! impl_vector_element_for_primitive {
398     ($ty:ident) => {
399         impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
400     };
401 }
402 
403 impl_vector_element_for_primitive!(u8);
404 impl_vector_element_for_primitive!(u16);
405 impl_vector_element_for_primitive!(u32);
406 impl_vector_element_for_primitive!(u64);
407 impl_vector_element_for_primitive!(usize);
408 impl_vector_element_for_primitive!(i8);
409 impl_vector_element_for_primitive!(i16);
410 impl_vector_element_for_primitive!(i32);
411 impl_vector_element_for_primitive!(i64);
412 impl_vector_element_for_primitive!(isize);
413 impl_vector_element_for_primitive!(f32);
414 impl_vector_element_for_primitive!(f64);
415 
416 impl_vector_element!("string", "CxxString", CxxString);
417