cxx/
cxx_vector.rs

1//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
2//! itself is exposed at the crate root.
3
4use crate::extern_type::ExternType;
5use crate::kind::Trivial;
6use crate::string::CxxString;
7use crate::unique_ptr::UniquePtr;
8use core::ffi::c_void;
9use core::fmt::{self, Debug};
10use core::iter::FusedIterator;
11use core::marker::{PhantomData, PhantomPinned};
12use core::mem::{self, ManuallyDrop, MaybeUninit};
13use core::pin::Pin;
14use 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)]
25pub struct CxxVector<T> {
26    // A thing, because repr(C) structs are not allowed to consist exclusively
27    // of PhantomData fields.
28    _void: [c_void; 0],
29    // The conceptual vector elements to ensure that autotraits are propagated
30    // correctly, e.g. CxxVector is UnwindSafe iff T is.
31    _elements: PhantomData<[T]>,
32    // Prevent unpin operation from Pin<&mut CxxVector<T>> to &mut CxxVector<T>.
33    _pinned: PhantomData<PhantomPinned>,
34}
35
36impl<T> CxxVector<T>
37where
38    T: VectorElement,
39{
40    /// Constructs a new heap allocated vector, wrapped by UniquePtr.
41    ///
42    /// The C++ vector is default constructed.
43    pub fn new() -> UniquePtr<Self> {
44        unsafe { UniquePtr::from_raw(T::__vector_new()) }
45    }
46
47    /// Returns the number of elements in the vector.
48    ///
49    /// Matches the behavior of C++ [std::vector\<T\>::size][size].
50    ///
51    /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
52    pub fn len(&self) -> usize {
53        T::__vector_size(self)
54    }
55
56    /// Returns the capacity of the vector.
57    ///
58    /// Matches the behavior of C++ [std::vector\<T\>::capacity][capacity].
59    ///
60    /// [capacity]: https://en.cppreference.com/w/cpp/container/vector/capacity
61    pub fn capacity(&self) -> usize {
62        T::__vector_capacity(self)
63    }
64
65    /// Returns true if the vector contains no elements.
66    ///
67    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
68    ///
69    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
70    pub fn is_empty(&self) -> bool {
71        self.len() == 0
72    }
73
74    /// Returns a reference to an element at the given position, or `None` if
75    /// out of bounds.
76    pub fn get(&self, pos: usize) -> Option<&T> {
77        if pos < self.len() {
78            Some(unsafe { self.get_unchecked(pos) })
79        } else {
80            None
81        }
82    }
83
84    /// Returns a pinned mutable reference to an element at the given position,
85    /// or `None` if out of bounds.
86    ///
87    /// This method cannot be named "get\_mut" due to a conflict with
88    /// `Pin::get_mut`.
89    #[doc(alias = "get_mut")]
90    pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
91        if pos < self.len() {
92            Some(unsafe { self.index_unchecked_mut(pos) })
93        } else {
94            None
95        }
96    }
97
98    /// Returns a reference to an element without doing bounds checking.
99    ///
100    /// This is generally not recommended, use with caution! Calling this method
101    /// with an out-of-bounds index is undefined behavior even if the resulting
102    /// reference is not used.
103    ///
104    /// Matches the behavior of C++
105    /// [std::vector\<T\>::operator\[\] const][operator_at].
106    ///
107    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
108    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
109        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
110        unsafe {
111            let ptr = T::__get_unchecked(this, pos) as *const T;
112            &*ptr
113        }
114    }
115
116    /// Returns a pinned mutable reference to an element without doing bounds
117    /// checking.
118    ///
119    /// This is generally not recommended, use with caution! Calling this method
120    /// with an out-of-bounds index is undefined behavior even if the resulting
121    /// reference is not used.
122    ///
123    /// Matches the behavior of C++
124    /// [std::vector\<T\>::operator\[\]][operator_at].
125    ///
126    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
127    ///
128    /// This method cannot be named "get\_unchecked\_mut" due to a conflict with
129    /// `Pin::get_unchecked_mut`.
130    #[doc(alias = "get_unchecked_mut")]
131    pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
132        unsafe {
133            let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos);
134            Pin::new_unchecked(&mut *ptr)
135        }
136    }
137
138    /// Returns a slice to the underlying contiguous array of elements.
139    pub fn as_slice(&self) -> &[T]
140    where
141        T: ExternType<Kind = Trivial>,
142    {
143        let len = self.len();
144        if len == 0 {
145            // The slice::from_raw_parts in the other branch requires a nonnull
146            // and properly aligned data ptr. C++ standard does not guarantee
147            // that data() on a vector with size 0 would return a nonnull
148            // pointer or sufficiently aligned pointer, so using it would be
149            // undefined behavior. Create our own empty slice in Rust instead
150            // which upholds the invariants.
151            &[]
152        } else {
153            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
154            let ptr = unsafe { T::__get_unchecked(this, 0) };
155            unsafe { slice::from_raw_parts(ptr, len) }
156        }
157    }
158
159    /// Returns a slice to the underlying contiguous array of elements by
160    /// mutable reference.
161    pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
162    where
163        T: ExternType<Kind = Trivial>,
164    {
165        let len = self.len();
166        if len == 0 {
167            &mut []
168        } else {
169            let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) };
170            unsafe { slice::from_raw_parts_mut(ptr, len) }
171        }
172    }
173
174    /// Returns an iterator over elements of type `&T`.
175    pub fn iter(&self) -> Iter<T> {
176        Iter { v: self, index: 0 }
177    }
178
179    /// Returns an iterator over elements of type `Pin<&mut T>`.
180    pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
181        IterMut { v: self, index: 0 }
182    }
183
184    /// Appends an element to the back of the vector.
185    ///
186    /// Matches the behavior of C++ [std::vector\<T\>::push_back][push_back].
187    ///
188    /// [push_back]: https://en.cppreference.com/w/cpp/container/vector/push_back
189    pub fn push(self: Pin<&mut Self>, value: T)
190    where
191        T: ExternType<Kind = Trivial>,
192    {
193        let mut value = ManuallyDrop::new(value);
194        unsafe {
195            // C++ calls move constructor followed by destructor on `value`.
196            T::__push_back(self, &mut value);
197        }
198    }
199
200    /// Removes the last element from a vector and returns it, or `None` if the
201    /// vector is empty.
202    pub fn pop(self: Pin<&mut Self>) -> Option<T>
203    where
204        T: ExternType<Kind = Trivial>,
205    {
206        if self.is_empty() {
207            None
208        } else {
209            let mut value = MaybeUninit::uninit();
210            Some(unsafe {
211                T::__pop_back(self, &mut value);
212                value.assume_init()
213            })
214        }
215    }
216
217    /// Ensures that this vector's capacity is at least `additional` elements
218    /// larger than its length.
219    ///
220    /// The capacity may be increased by more than `additional` elements if the
221    /// implementation chooses, to amortize the cost of frequent reallocations.
222    ///
223    /// **The meaning of the argument is not the same as
224    /// [std::vector\<T\>::reserve][reserve] in C++.** The C++ standard library
225    /// and Rust standard library both have a `reserve` method on vectors, but
226    /// in C++ code the argument always refers to total capacity, whereas in
227    /// Rust code it always refers to additional capacity. This API on
228    /// `CxxVector` follows the Rust convention, the same way that for the
229    /// length accessor we use the Rust conventional `len()` naming and not C++
230    /// `size()`.
231    ///
232    /// # Panics
233    ///
234    /// Panics if the new capacity overflows usize.
235    ///
236    /// [reserve]: https://en.cppreference.com/w/cpp/container/vector/reserve.html
237    pub fn reserve(self: Pin<&mut Self>, additional: usize) {
238        let new_cap = self
239            .len()
240            .checked_add(additional)
241            .expect("CxxVector capacity overflow");
242        unsafe { T::__reserve(self, new_cap) }
243    }
244}
245
246impl<T> Extend<T> for Pin<&mut CxxVector<T>>
247where
248    T: ExternType<Kind = Trivial> + VectorElement,
249{
250    fn extend<I>(&mut self, iter: I)
251    where
252        I: IntoIterator<Item = T>,
253    {
254        let iter = iter.into_iter();
255        self.as_mut().reserve(iter.size_hint().0);
256        for element in iter {
257            self.as_mut().push(element);
258        }
259    }
260}
261
262/// Iterator over elements of a `CxxVector` by shared reference.
263///
264/// The iterator element type is `&'a T`.
265pub struct Iter<'a, T> {
266    v: &'a CxxVector<T>,
267    index: usize,
268}
269
270impl<'a, T> IntoIterator for &'a CxxVector<T>
271where
272    T: VectorElement,
273{
274    type Item = &'a T;
275    type IntoIter = Iter<'a, T>;
276
277    fn into_iter(self) -> Self::IntoIter {
278        self.iter()
279    }
280}
281
282impl<'a, T> Iterator for Iter<'a, T>
283where
284    T: VectorElement,
285{
286    type Item = &'a T;
287
288    fn next(&mut self) -> Option<Self::Item> {
289        let next = self.v.get(self.index)?;
290        self.index += 1;
291        Some(next)
292    }
293
294    fn size_hint(&self) -> (usize, Option<usize>) {
295        let len = self.len();
296        (len, Some(len))
297    }
298}
299
300impl<'a, T> ExactSizeIterator for Iter<'a, T>
301where
302    T: VectorElement,
303{
304    fn len(&self) -> usize {
305        self.v.len() - self.index
306    }
307}
308
309impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
310
311/// Iterator over elements of a `CxxVector` by pinned mutable reference.
312///
313/// The iterator element type is `Pin<&'a mut T>`.
314pub struct IterMut<'a, T> {
315    v: Pin<&'a mut CxxVector<T>>,
316    index: usize,
317}
318
319impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>>
320where
321    T: VectorElement,
322{
323    type Item = Pin<&'a mut T>;
324    type IntoIter = IterMut<'a, T>;
325
326    fn into_iter(self) -> Self::IntoIter {
327        self.iter_mut()
328    }
329}
330
331impl<'a, T> Iterator for IterMut<'a, T>
332where
333    T: VectorElement,
334{
335    type Item = Pin<&'a mut T>;
336
337    fn next(&mut self) -> Option<Self::Item> {
338        let next = self.v.as_mut().index_mut(self.index)?;
339        self.index += 1;
340        // Extend lifetime to allow simultaneous holding of nonoverlapping
341        // elements, analogous to slice::split_first_mut.
342        unsafe {
343            let ptr = Pin::into_inner_unchecked(next) as *mut T;
344            Some(Pin::new_unchecked(&mut *ptr))
345        }
346    }
347
348    fn size_hint(&self) -> (usize, Option<usize>) {
349        let len = self.len();
350        (len, Some(len))
351    }
352}
353
354impl<'a, T> ExactSizeIterator for IterMut<'a, T>
355where
356    T: VectorElement,
357{
358    fn len(&self) -> usize {
359        self.v.len() - self.index
360    }
361}
362
363impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
364
365impl<T> Debug for CxxVector<T>
366where
367    T: VectorElement + Debug,
368{
369    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
370        formatter.debug_list().entries(self).finish()
371    }
372}
373
374/// Trait bound for types which may be used as the `T` inside of a
375/// `CxxVector<T>` in generic code.
376///
377/// This trait has no publicly callable or implementable methods. Implementing
378/// it outside of the CXX codebase requires using [explicit shim trait impls],
379/// adding the line `impl CxxVector<MyType> {}` in the same `cxx::bridge` that
380/// defines `MyType`.
381///
382/// # Example
383///
384/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
385/// in generic code.
386///
387/// ```
388/// use cxx::vector::{CxxVector, VectorElement};
389/// use std::fmt::Display;
390///
391/// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
392/// where
393///     T: VectorElement + Display,
394/// {
395///     println!("the vector elements are:");
396///     for element in vector {
397///         println!("  • {}", element);
398///     }
399/// }
400/// ```
401///
402/// Writing the same generic function without a `VectorElement` trait bound
403/// would not compile.
404///
405/// [explicit shim trait impls]: https://cxx.rs/extern-c++.html#explicit-shim-trait-impls
406pub unsafe trait VectorElement: Sized {
407    #[doc(hidden)]
408    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
409    #[doc(hidden)]
410    fn __vector_new() -> *mut CxxVector<Self>;
411    #[doc(hidden)]
412    fn __vector_size(v: &CxxVector<Self>) -> usize;
413    #[doc(hidden)]
414    fn __vector_capacity(v: &CxxVector<Self>) -> usize;
415    #[doc(hidden)]
416    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
417    #[doc(hidden)]
418    unsafe fn __reserve(v: Pin<&mut CxxVector<Self>>, new_cap: usize);
419    #[doc(hidden)]
420    unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut ManuallyDrop<Self>) {
421        // Opaque C type vector elements do not get this method because they can
422        // never exist by value on the Rust side of the bridge.
423        let _ = v;
424        let _ = value;
425        unreachable!()
426    }
427    #[doc(hidden)]
428    unsafe fn __pop_back(v: Pin<&mut CxxVector<Self>>, out: &mut MaybeUninit<Self>) {
429        // Opaque C type vector elements do not get this method because they can
430        // never exist by value on the Rust side of the bridge.
431        let _ = v;
432        let _ = out;
433        unreachable!()
434    }
435    #[doc(hidden)]
436    fn __unique_ptr_null() -> MaybeUninit<*mut c_void>;
437    #[doc(hidden)]
438    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void>;
439    #[doc(hidden)]
440    unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self>;
441    #[doc(hidden)]
442    unsafe fn __unique_ptr_release(repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self>;
443    #[doc(hidden)]
444    unsafe fn __unique_ptr_drop(repr: MaybeUninit<*mut c_void>);
445}
446
447macro_rules! vector_element_by_value_methods {
448    (opaque, $segment:expr, $ty:ty) => {};
449    (trivial, $segment:expr, $ty:ty) => {
450        unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) {
451            extern "C" {
452                #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")]
453                fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>);
454            }
455            unsafe { __push_back(v, value) }
456        }
457        unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) {
458            extern "C" {
459                #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")]
460                fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>);
461            }
462            unsafe { __pop_back(v, out) }
463        }
464    };
465}
466
467macro_rules! impl_vector_element {
468    ($kind:ident, $segment:expr, $name:expr, $ty:ty) => {
469        const_assert_eq!(0, mem::size_of::<CxxVector<$ty>>());
470        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
471
472        unsafe impl VectorElement for $ty {
473            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
474                f.write_str($name)
475            }
476            fn __vector_new() -> *mut CxxVector<Self> {
477                extern "C" {
478                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$new")]
479                    fn __vector_new() -> *mut CxxVector<$ty>;
480                }
481                unsafe { __vector_new() }
482            }
483            fn __vector_size(v: &CxxVector<$ty>) -> usize {
484                extern "C" {
485                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
486                    fn __vector_size(_: &CxxVector<$ty>) -> usize;
487                }
488                unsafe { __vector_size(v) }
489            }
490            fn __vector_capacity(v: &CxxVector<$ty>) -> usize {
491                extern "C" {
492                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$capacity")]
493                    fn __vector_capacity(_: &CxxVector<$ty>) -> usize;
494                }
495                unsafe { __vector_capacity(v) }
496            }
497            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
498                extern "C" {
499                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
500                    fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
501                }
502                unsafe { __get_unchecked(v, pos) }
503            }
504            unsafe fn __reserve(v: Pin<&mut CxxVector<$ty>>, new_cap: usize) {
505                extern "C" {
506                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$reserve")]
507                    fn __reserve(_: Pin<&mut CxxVector<$ty>>, _: usize);
508                }
509                unsafe { __reserve(v, new_cap) }
510            }
511            vector_element_by_value_methods!($kind, $segment, $ty);
512            fn __unique_ptr_null() -> MaybeUninit<*mut c_void> {
513                extern "C" {
514                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
515                    fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>);
516                }
517                let mut repr = MaybeUninit::uninit();
518                unsafe { __unique_ptr_null(&mut repr) }
519                repr
520            }
521            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> {
522                extern "C" {
523                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
524                    fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>);
525                }
526                let mut repr = MaybeUninit::uninit();
527                unsafe { __unique_ptr_raw(&mut repr, raw) }
528                repr
529            }
530            unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> {
531                extern "C" {
532                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
533                    fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>;
534                }
535                unsafe { __unique_ptr_get(&repr) }
536            }
537            unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> {
538                extern "C" {
539                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
540                    fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>;
541                }
542                unsafe { __unique_ptr_release(&mut repr) }
543            }
544            unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) {
545                extern "C" {
546                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
547                    fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>);
548                }
549                unsafe { __unique_ptr_drop(&mut repr) }
550            }
551        }
552    };
553}
554
555macro_rules! impl_vector_element_for_primitive {
556    ($ty:ident) => {
557        impl_vector_element!(trivial, stringify!($ty), stringify!($ty), $ty);
558    };
559}
560
561impl_vector_element_for_primitive!(u8);
562impl_vector_element_for_primitive!(u16);
563impl_vector_element_for_primitive!(u32);
564impl_vector_element_for_primitive!(u64);
565impl_vector_element_for_primitive!(usize);
566impl_vector_element_for_primitive!(i8);
567impl_vector_element_for_primitive!(i16);
568impl_vector_element_for_primitive!(i32);
569impl_vector_element_for_primitive!(i64);
570impl_vector_element_for_primitive!(isize);
571impl_vector_element_for_primitive!(f32);
572impl_vector_element_for_primitive!(f64);
573
574impl_vector_element!(opaque, "string", "CxxString", CxxString);