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