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 true if the vector contains no elements.
57    ///
58    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
59    ///
60    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
61    pub fn is_empty(&self) -> bool {
62        self.len() == 0
63    }
64
65    /// Returns a reference to an element at the given position, or `None` if
66    /// out of bounds.
67    pub fn get(&self, pos: usize) -> Option<&T> {
68        if pos < self.len() {
69            Some(unsafe { self.get_unchecked(pos) })
70        } else {
71            None
72        }
73    }
74
75    /// Returns a pinned mutable reference to an element at the given position,
76    /// or `None` if out of bounds.
77    ///
78    /// This method cannot be named "get\_mut" due to a conflict with
79    /// `Pin::get_mut`.
80    #[doc(alias = "get_mut")]
81    pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
82        if pos < self.len() {
83            Some(unsafe { self.index_unchecked_mut(pos) })
84        } else {
85            None
86        }
87    }
88
89    /// Returns a reference to an element without doing bounds 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\[\] const][operator_at].
97    ///
98    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
99    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
100        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
101        unsafe {
102            let ptr = T::__get_unchecked(this, pos) as *const T;
103            &*ptr
104        }
105    }
106
107    /// Returns a pinned mutable reference to an element without doing bounds
108    /// checking.
109    ///
110    /// This is generally not recommended, use with caution! Calling this method
111    /// with an out-of-bounds index is undefined behavior even if the resulting
112    /// reference is not used.
113    ///
114    /// Matches the behavior of C++
115    /// [std::vector\<T\>::operator\[\]][operator_at].
116    ///
117    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
118    ///
119    /// This method cannot be named "get\_unchecked\_mut" due to a conflict with
120    /// `Pin::get_unchecked_mut`.
121    #[doc(alias = "get_unchecked_mut")]
122    pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
123        unsafe {
124            let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos);
125            Pin::new_unchecked(&mut *ptr)
126        }
127    }
128
129    /// Returns a slice to the underlying contiguous array of elements.
130    pub fn as_slice(&self) -> &[T]
131    where
132        T: ExternType<Kind = Trivial>,
133    {
134        let len = self.len();
135        if len == 0 {
136            // The slice::from_raw_parts in the other branch requires a nonnull
137            // and properly aligned data ptr. C++ standard does not guarantee
138            // that data() on a vector with size 0 would return a nonnull
139            // pointer or sufficiently aligned pointer, so using it would be
140            // undefined behavior. Create our own empty slice in Rust instead
141            // which upholds the invariants.
142            &[]
143        } else {
144            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
145            let ptr = unsafe { T::__get_unchecked(this, 0) };
146            unsafe { slice::from_raw_parts(ptr, len) }
147        }
148    }
149
150    /// Returns a slice to the underlying contiguous array of elements by
151    /// mutable reference.
152    pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
153    where
154        T: ExternType<Kind = Trivial>,
155    {
156        let len = self.len();
157        if len == 0 {
158            &mut []
159        } else {
160            let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) };
161            unsafe { slice::from_raw_parts_mut(ptr, len) }
162        }
163    }
164
165    /// Returns an iterator over elements of type `&T`.
166    pub fn iter(&self) -> Iter<T> {
167        Iter { v: self, index: 0 }
168    }
169
170    /// Returns an iterator over elements of type `Pin<&mut T>`.
171    pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
172        IterMut { v: self, index: 0 }
173    }
174
175    /// Appends an element to the back of the vector.
176    ///
177    /// Matches the behavior of C++ [std::vector\<T\>::push_back][push_back].
178    ///
179    /// [push_back]: https://en.cppreference.com/w/cpp/container/vector/push_back
180    pub fn push(self: Pin<&mut Self>, value: T)
181    where
182        T: ExternType<Kind = Trivial>,
183    {
184        let mut value = ManuallyDrop::new(value);
185        unsafe {
186            // C++ calls move constructor followed by destructor on `value`.
187            T::__push_back(self, &mut value);
188        }
189    }
190
191    /// Removes the last element from a vector and returns it, or `None` if the
192    /// vector is empty.
193    pub fn pop(self: Pin<&mut Self>) -> Option<T>
194    where
195        T: ExternType<Kind = Trivial>,
196    {
197        if self.is_empty() {
198            None
199        } else {
200            let mut value = MaybeUninit::uninit();
201            Some(unsafe {
202                T::__pop_back(self, &mut value);
203                value.assume_init()
204            })
205        }
206    }
207}
208
209/// Iterator over elements of a `CxxVector` by shared reference.
210///
211/// The iterator element type is `&'a T`.
212pub struct Iter<'a, T> {
213    v: &'a CxxVector<T>,
214    index: usize,
215}
216
217impl<'a, T> IntoIterator for &'a CxxVector<T>
218where
219    T: VectorElement,
220{
221    type Item = &'a T;
222    type IntoIter = Iter<'a, T>;
223
224    fn into_iter(self) -> Self::IntoIter {
225        self.iter()
226    }
227}
228
229impl<'a, T> Iterator for Iter<'a, T>
230where
231    T: VectorElement,
232{
233    type Item = &'a T;
234
235    fn next(&mut self) -> Option<Self::Item> {
236        let next = self.v.get(self.index)?;
237        self.index += 1;
238        Some(next)
239    }
240
241    fn size_hint(&self) -> (usize, Option<usize>) {
242        let len = self.len();
243        (len, Some(len))
244    }
245}
246
247impl<'a, T> ExactSizeIterator for Iter<'a, T>
248where
249    T: VectorElement,
250{
251    fn len(&self) -> usize {
252        self.v.len() - self.index
253    }
254}
255
256impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
257
258/// Iterator over elements of a `CxxVector` by pinned mutable reference.
259///
260/// The iterator element type is `Pin<&'a mut T>`.
261pub struct IterMut<'a, T> {
262    v: Pin<&'a mut CxxVector<T>>,
263    index: usize,
264}
265
266impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>>
267where
268    T: VectorElement,
269{
270    type Item = Pin<&'a mut T>;
271    type IntoIter = IterMut<'a, T>;
272
273    fn into_iter(self) -> Self::IntoIter {
274        self.iter_mut()
275    }
276}
277
278impl<'a, T> Iterator for IterMut<'a, T>
279where
280    T: VectorElement,
281{
282    type Item = Pin<&'a mut T>;
283
284    fn next(&mut self) -> Option<Self::Item> {
285        let next = self.v.as_mut().index_mut(self.index)?;
286        self.index += 1;
287        // Extend lifetime to allow simultaneous holding of nonoverlapping
288        // elements, analogous to slice::split_first_mut.
289        unsafe {
290            let ptr = Pin::into_inner_unchecked(next) as *mut T;
291            Some(Pin::new_unchecked(&mut *ptr))
292        }
293    }
294
295    fn size_hint(&self) -> (usize, Option<usize>) {
296        let len = self.len();
297        (len, Some(len))
298    }
299}
300
301impl<'a, T> ExactSizeIterator for IterMut<'a, T>
302where
303    T: VectorElement,
304{
305    fn len(&self) -> usize {
306        self.v.len() - self.index
307    }
308}
309
310impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
311
312impl<T> Debug for CxxVector<T>
313where
314    T: VectorElement + Debug,
315{
316    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
317        formatter.debug_list().entries(self).finish()
318    }
319}
320
321/// Trait bound for types which may be used as the `T` inside of a
322/// `CxxVector<T>` in generic code.
323///
324/// This trait has no publicly callable or implementable methods. Implementing
325/// it outside of the CXX codebase requires using [explicit shim trait impls],
326/// adding the line `impl CxxVector<MyType> {}` in the same `cxx::bridge` that
327/// defines `MyType`.
328///
329/// # Example
330///
331/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
332/// in generic code.
333///
334/// ```
335/// use cxx::vector::{CxxVector, VectorElement};
336/// use std::fmt::Display;
337///
338/// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
339/// where
340///     T: VectorElement + Display,
341/// {
342///     println!("the vector elements are:");
343///     for element in vector {
344///         println!("  • {}", element);
345///     }
346/// }
347/// ```
348///
349/// Writing the same generic function without a `VectorElement` trait bound
350/// would not compile.
351///
352/// [explicit shim trait impls]: https://cxx.rs/extern-c++.html#explicit-shim-trait-impls
353pub unsafe trait VectorElement: Sized {
354    #[doc(hidden)]
355    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
356    #[doc(hidden)]
357    fn __vector_new() -> *mut CxxVector<Self>;
358    #[doc(hidden)]
359    fn __vector_size(v: &CxxVector<Self>) -> usize;
360    #[doc(hidden)]
361    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
362    #[doc(hidden)]
363    unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut ManuallyDrop<Self>) {
364        // Opaque C type vector elements do not get this method because they can
365        // never exist by value on the Rust side of the bridge.
366        let _ = v;
367        let _ = value;
368        unreachable!()
369    }
370    #[doc(hidden)]
371    unsafe fn __pop_back(v: Pin<&mut CxxVector<Self>>, out: &mut MaybeUninit<Self>) {
372        // Opaque C type vector elements do not get this method because they can
373        // never exist by value on the Rust side of the bridge.
374        let _ = v;
375        let _ = out;
376        unreachable!()
377    }
378    #[doc(hidden)]
379    fn __unique_ptr_null() -> MaybeUninit<*mut c_void>;
380    #[doc(hidden)]
381    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void>;
382    #[doc(hidden)]
383    unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self>;
384    #[doc(hidden)]
385    unsafe fn __unique_ptr_release(repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self>;
386    #[doc(hidden)]
387    unsafe fn __unique_ptr_drop(repr: MaybeUninit<*mut c_void>);
388}
389
390macro_rules! vector_element_by_value_methods {
391    (opaque, $segment:expr, $ty:ty) => {};
392    (trivial, $segment:expr, $ty:ty) => {
393        unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) {
394            extern "C" {
395                #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")]
396                fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>);
397            }
398            unsafe { __push_back(v, value) }
399        }
400        unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) {
401            extern "C" {
402                #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")]
403                fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>);
404            }
405            unsafe { __pop_back(v, out) }
406        }
407    };
408}
409
410macro_rules! impl_vector_element {
411    ($kind:ident, $segment:expr, $name:expr, $ty:ty) => {
412        const_assert_eq!(0, mem::size_of::<CxxVector<$ty>>());
413        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
414
415        unsafe impl VectorElement for $ty {
416            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
417                f.write_str($name)
418            }
419            fn __vector_new() -> *mut CxxVector<Self> {
420                extern "C" {
421                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$new")]
422                    fn __vector_new() -> *mut CxxVector<$ty>;
423                }
424                unsafe { __vector_new() }
425            }
426            fn __vector_size(v: &CxxVector<$ty>) -> usize {
427                extern "C" {
428                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
429                    fn __vector_size(_: &CxxVector<$ty>) -> usize;
430                }
431                unsafe { __vector_size(v) }
432            }
433            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
434                extern "C" {
435                    #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
436                    fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
437                }
438                unsafe { __get_unchecked(v, pos) }
439            }
440            vector_element_by_value_methods!($kind, $segment, $ty);
441            fn __unique_ptr_null() -> MaybeUninit<*mut c_void> {
442                extern "C" {
443                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
444                    fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>);
445                }
446                let mut repr = MaybeUninit::uninit();
447                unsafe { __unique_ptr_null(&mut repr) }
448                repr
449            }
450            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> {
451                extern "C" {
452                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
453                    fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>);
454                }
455                let mut repr = MaybeUninit::uninit();
456                unsafe { __unique_ptr_raw(&mut repr, raw) }
457                repr
458            }
459            unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> {
460                extern "C" {
461                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
462                    fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>;
463                }
464                unsafe { __unique_ptr_get(&repr) }
465            }
466            unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> {
467                extern "C" {
468                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
469                    fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>;
470                }
471                unsafe { __unique_ptr_release(&mut repr) }
472            }
473            unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) {
474                extern "C" {
475                    #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
476                    fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>);
477                }
478                unsafe { __unique_ptr_drop(&mut repr) }
479            }
480        }
481    };
482}
483
484macro_rules! impl_vector_element_for_primitive {
485    ($ty:ident) => {
486        impl_vector_element!(trivial, stringify!($ty), stringify!($ty), $ty);
487    };
488}
489
490impl_vector_element_for_primitive!(u8);
491impl_vector_element_for_primitive!(u16);
492impl_vector_element_for_primitive!(u32);
493impl_vector_element_for_primitive!(u64);
494impl_vector_element_for_primitive!(usize);
495impl_vector_element_for_primitive!(i8);
496impl_vector_element_for_primitive!(i16);
497impl_vector_element_for_primitive!(i32);
498impl_vector_element_for_primitive!(i64);
499impl_vector_element_for_primitive!(isize);
500impl_vector_element_for_primitive!(f32);
501impl_vector_element_for_primitive!(f64);
502
503impl_vector_element!(opaque, "string", "CxxString", CxxString);