opencv/manual/core/
vector.rs

1use std::borrow::Borrow;
2use std::ffi::c_void;
3use std::iter::FromIterator;
4use std::marker::PhantomData;
5use std::mem::ManuallyDrop;
6use std::{fmt, mem, slice};
7
8pub use iter::{VectorIterator, VectorRefIterator};
9pub use vector_extern::{VectorExtern, VectorExternCopyNonBool};
10
11use crate::boxed_ref::BoxedRef;
12use crate::platform_types::size_t;
13use crate::traits::{Boxed, OpenCVFromExtern, OpenCVIntoExternContainer, OpenCVType, OpenCVTypeExternContainer};
14use crate::Result;
15
16mod iter;
17mod vector_extern;
18
19/// Wrapper for C++ [std::vector](https://en.cppreference.com/w/cpp/container/vector)
20pub struct Vector<T>
21where
22	Self: VectorExtern<T>,
23{
24	ptr: *mut c_void,
25	_d: PhantomData<T>,
26}
27
28impl<T> Vector<T>
29where
30	Self: VectorExtern<T>,
31{
32	/// Create a new Vector
33	#[inline]
34	pub fn new() -> Self {
35		unsafe { Self::from_raw(Self::extern_new()) }
36	}
37
38	/// Create a Vector with pre-defined capacity
39	#[inline]
40	pub fn with_capacity(capacity: size_t) -> Self {
41		let mut out = Self::new();
42		out.reserve(capacity);
43		out
44	}
45
46	/// Create a Vector from iterator
47	#[inline]
48	pub fn from_iter<'a>(s: impl IntoIterator<Item = <T as OpenCVType<'a>>::Arg>) -> Self
49	where
50		T: for<'t> OpenCVType<'t>,
51	{
52		#![allow(clippy::should_implement_trait)]
53		let mut out = Self::new();
54		out.extend(s);
55		out
56	}
57
58	/// Create a Vector from slice, the element type needs to be Copy (and not bool)
59	#[inline]
60	pub fn from_slice(s: &[T]) -> Self
61	where
62		Self: VectorExternCopyNonBool<T>,
63	{
64		unsafe { Self::from_raw(Self::extern_from_slice(s.as_ptr(), s.len())) }
65	}
66
67	#[inline]
68	pub fn from_elem<'a>(elem: <T as OpenCVType<'a>>::Arg, n: size_t) -> Self
69	where
70		T: for<'t> OpenCVType<'t>,
71		<T as OpenCVType<'a>>::Arg: Clone,
72	{
73		let mut out = Self::with_capacity(n);
74		for _ in 0..n {
75			out.push(elem.clone());
76		}
77		out
78	}
79
80	/// Return Vector length
81	#[inline]
82	pub fn len(&self) -> size_t {
83		unsafe { self.extern_len() }
84	}
85
86	/// Return true if Vector is empty
87	#[inline]
88	pub fn is_empty(&self) -> bool {
89		unsafe { self.extern_is_empty() }
90	}
91
92	/// Return Vector current capacity
93	#[inline]
94	pub fn capacity(&self) -> size_t {
95		unsafe { self.extern_capacity() }
96	}
97
98	/// Free extra capacity
99	#[inline]
100	pub fn shrink_to_fit(&mut self) {
101		unsafe { self.extern_shrink_to_fit() }
102	}
103
104	/// Reserve capacity for `additional` new elements
105	#[inline]
106	pub fn reserve(&mut self, additional: size_t) {
107		unsafe { self.extern_reserve(additional) }
108	}
109
110	/// Remove all elements
111	#[inline]
112	pub fn clear(&mut self) {
113		unsafe { self.extern_clear() }
114	}
115
116	/// Remove the element at the specified `index`
117	#[inline]
118	pub fn remove(&mut self, index: size_t) -> Result<()> {
119		vector_index_check(index, self.len())?;
120		unsafe { self.extern_remove(index) }
121		Ok(())
122	}
123
124	/// Swap 2 elements in the Vector
125	#[inline]
126	pub fn swap(&mut self, index1: size_t, index2: size_t) -> Result<()> {
127		let len = self.len();
128		vector_index_check(index1, len)?;
129		vector_index_check(index2, len)?;
130		if index1 != index2 {
131			unsafe { self.extern_swap(index1, index2) }
132		}
133		Ok(())
134	}
135
136	/// Add new element
137	#[inline]
138	pub fn push(&mut self, val: <T as OpenCVType>::Arg)
139	where
140		T: for<'t> OpenCVType<'t>,
141	{
142		let val = val.opencv_into_extern_container_nofail();
143		unsafe { self.extern_push(val.opencv_as_extern()) }
144	}
145
146	#[inline]
147	pub(crate) fn push_owned(&mut self, val: T)
148	where
149		T: OpenCVIntoExternContainer,
150	{
151		let val = val.opencv_into_extern_container_nofail();
152		unsafe { self.extern_push_owned(val.opencv_as_extern()) }
153	}
154
155	/// Insert a new element at the specified `index`
156	#[inline]
157	pub fn insert(&mut self, index: size_t, val: <T as OpenCVType>::Arg) -> Result<()>
158	where
159		T: for<'t> OpenCVType<'t>,
160	{
161		vector_index_check(index, self.len() + 1)?;
162		let val = val.opencv_into_extern_container()?;
163		unsafe { self.extern_insert(index, val.opencv_as_extern()) }
164		Ok(())
165	}
166
167	/// Set element at the specified `index`
168	#[inline]
169	pub fn set(&mut self, index: size_t, val: <T as OpenCVType>::Arg) -> Result<()>
170	where
171		T: for<'t> OpenCVType<'t>,
172	{
173		vector_index_check(index, self.len())?;
174		let val = val.opencv_into_extern_container()?;
175		unsafe { self.extern_set(index, val.opencv_as_extern()) }
176		Ok(())
177	}
178
179	/// Same as `set()` but without bounds checking
180	/// # Safety
181	/// Caller must ensure that the specified `index` is within the `Vector` bounds
182	#[inline]
183	pub unsafe fn set_unchecked(&mut self, index: size_t, val: <T as OpenCVType>::Arg)
184	where
185		T: for<'t> OpenCVType<'t>,
186	{
187		let val = val.opencv_into_extern_container_nofail();
188		unsafe { self.extern_set(index, val.opencv_as_extern()) }
189	}
190
191	/// Get element at the specified `index`
192	#[inline]
193	pub fn get(&self, index: size_t) -> Result<T>
194	where
195		T: OpenCVFromExtern,
196	{
197		vector_index_check(index, self.len())?;
198		Ok(unsafe { self.get_unchecked(index) })
199	}
200
201	/// Same as `get()` but without bounds checking
202	/// # Safety
203	/// Caller must ensure that the specified `index` is within the `Vector` bounds
204	#[inline]
205	pub unsafe fn get_unchecked(&self, index: size_t) -> T
206	where
207		T: OpenCVFromExtern,
208	{
209		let val = unsafe { self.extern_get(index) };
210		unsafe { T::opencv_from_extern(val) }
211	}
212
213	#[inline]
214	pub fn iter(&self) -> VectorRefIterator<T> {
215		VectorRefIterator::new(self)
216	}
217
218	/// Return slice to the elements of the array.
219	///
220	/// This method is only available for OpenCV types that are Copy, except for bool
221	/// because bool is handled in a special way on the C++ side.
222	#[inline]
223	pub fn as_slice(&self) -> &[T]
224	where
225		Self: VectorExternCopyNonBool<T>,
226	{
227		let data = unsafe { self.extern_data() };
228		if data.is_null() {
229			&[]
230		} else {
231			unsafe { slice::from_raw_parts(data, self.len()) }
232		}
233	}
234
235	/// Return mutable slice to the elements of the array.
236	///
237	/// This method is only available for OpenCV types that are Copy, except for bool
238	/// because bool is handled in a special way on the C++ side.
239	#[inline]
240	pub fn as_mut_slice(&mut self) -> &mut [T]
241	where
242		Self: VectorExternCopyNonBool<T>,
243	{
244		let data = unsafe { self.extern_data_mut() };
245		if data.is_null() {
246			&mut []
247		} else {
248			unsafe { slice::from_raw_parts_mut(data, self.len()) }
249		}
250	}
251}
252
253pub trait VectorToVec {
254	type Element;
255
256	/// Convert `Vector` to `Vec`
257	fn to_vec(&self) -> Vec<Self::Element>;
258}
259
260impl<T> Default for Vector<T>
261where
262	Self: VectorExtern<T>,
263{
264	#[inline]
265	fn default() -> Vector<T> {
266		Vector::new()
267	}
268}
269
270impl<T> From<Vector<T>> for Vec<T>
271where
272	Vector<T>: VectorExtern<T> + VectorToVec<Element = T>,
273{
274	#[inline]
275	fn from(from: Vector<T>) -> Self {
276		from.to_vec()
277	}
278}
279
280impl<T: for<'o> OpenCVType<'o>> From<Vec<<T as OpenCVType<'_>>::Arg>> for Vector<T>
281where
282	Vector<T>: VectorExtern<T>,
283{
284	#[inline]
285	fn from(from: Vec<<T as OpenCVType<'_>>::Arg>) -> Self {
286		Self::from_iter(from)
287	}
288}
289
290impl<'a, T: for<'o> OpenCVType<'o>> FromIterator<<T as OpenCVType<'a>>::Arg> for Vector<T>
291where
292	Self: VectorExtern<T>,
293{
294	#[inline]
295	fn from_iter<I: IntoIterator<Item = <T as OpenCVType<'a>>::Arg>>(s: I) -> Vector<T> {
296		Self::from_iter(s)
297	}
298}
299
300impl<T> AsRef<[T]> for Vector<T>
301where
302	Self: VectorExtern<T> + VectorExternCopyNonBool<T>,
303{
304	#[inline]
305	fn as_ref(&self) -> &[T] {
306		self.as_slice()
307	}
308}
309
310impl<T> Borrow<[T]> for Vector<T>
311where
312	Self: VectorExtern<T> + VectorExternCopyNonBool<T>,
313{
314	#[inline]
315	fn borrow(&self) -> &[T] {
316		self.as_slice()
317	}
318}
319
320impl<T: OpenCVFromExtern + fmt::Debug> fmt::Debug for Vector<T>
321where
322	Self: VectorExtern<T>,
323{
324	#[inline]
325	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
326		f.debug_list().entries(self).finish()
327	}
328}
329
330impl<T> Drop for Vector<T>
331where
332	Self: VectorExtern<T>,
333{
334	fn drop(&mut self) {
335		unsafe { self.extern_delete() }
336	}
337}
338
339unsafe impl<T: Send> Send for Vector<T> where Self: VectorExtern<T> {}
340
341unsafe impl<T: Sync> Sync for Vector<T> where Self: VectorExtern<T> {}
342
343impl<'a, T: for<'o> OpenCVType<'o>> Extend<<T as OpenCVType<'a>>::Arg> for Vector<T>
344where
345	Self: VectorExtern<T>,
346{
347	fn extend<I: IntoIterator<Item = <T as OpenCVType<'a>>::Arg>>(&mut self, s: I) {
348		let s = s.into_iter();
349		let (lo, hi) = s.size_hint();
350		self.reserve(hi.unwrap_or(lo));
351		s.for_each(|elem| {
352			self.push(elem);
353		});
354	}
355}
356
357impl<T> Boxed for Vector<T>
358where
359	Self: VectorExtern<T>,
360{
361	#[inline]
362	unsafe fn from_raw(ptr: *mut c_void) -> Self {
363		Self { ptr, _d: PhantomData }
364	}
365
366	#[inline]
367	fn into_raw(self) -> *mut c_void {
368		ManuallyDrop::new(self).ptr
369	}
370
371	#[inline]
372	fn as_raw(&self) -> *const c_void {
373		self.ptr
374	}
375
376	#[inline]
377	fn as_raw_mut(&mut self) -> *mut c_void {
378		self.ptr
379	}
380}
381
382impl<'b, T: Boxed> Vector<BoxedRef<'b, T>>
383where
384	Self: VectorExtern<BoxedRef<'b, T>>,
385	Vector<T>: VectorExtern<T>,
386{
387	/// Transmutes a `&Vector<BoxedRef<T>>` into a `&Vector<T>`. This is safe as `BoxedRef` is a transparent wrapper around `T`,
388	/// but it breaks the lifetime guards imposed by `BoxedRef`, so this is a crate private function.
389	pub(crate) fn as_non_ref_vec(&self) -> &Vector<T> {
390		unsafe { mem::transmute::<_, &Vector<T>>(self) }
391	}
392}
393
394#[inline(always)]
395fn vector_index_check(index: size_t, len: size_t) -> Result<()> {
396	if index >= len {
397		Err(crate::Error::new(
398			crate::core::StsOutOfRange,
399			format!("Index: {index} out of bounds: 0..{len}"),
400		))
401	} else {
402		Ok(())
403	}
404}