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