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