cxx_qt_lib/core/qvector/
mod.rs

1// SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5
6#[cfg(feature = "qt_gui")]
7use crate::QColor;
8#[cfg(not(target_os = "emscripten"))]
9use crate::QDateTime;
10use crate::{
11    QByteArray, QDate, QLine, QLineF, QMargins, QMarginsF, QPersistentModelIndex, QPoint, QPointF,
12    QRect, QRectF, QSize, QSizeF, QString, QTime, QUrl, QVariant,
13};
14use core::{marker::PhantomData, mem::MaybeUninit};
15use cxx::{type_id, ExternType};
16
17/// The QVector class is a template class that provides a dynamic array.
18///
19/// To use QVector with a custom type, implement the [`QVectorElement`] trait for T.
20#[repr(C)]
21pub struct QVector<T>
22where
23    T: QVectorElement,
24{
25    /// The layout has changed between Qt 5 and Qt 6
26    ///
27    /// Qt5 QVector has one pointer as a member
28    /// Qt6 QVector/QList has one member, which contains two pointers and a size_t
29    #[cfg(cxxqt_qt_version_major = "5")]
30    _space: MaybeUninit<usize>,
31    #[cfg(cxxqt_qt_version_major = "6")]
32    _space: MaybeUninit<[usize; 3]>,
33    _value: PhantomData<T>,
34}
35
36impl<T> Clone for QVector<T>
37where
38    T: QVectorElement,
39{
40    /// Constructs a copy of the QVector.
41    fn clone(&self) -> Self {
42        T::clone(self)
43    }
44}
45
46impl<T> Default for QVector<T>
47where
48    T: QVectorElement,
49{
50    /// Constructs an empty vector.
51    fn default() -> Self {
52        T::default()
53    }
54}
55
56impl<T> Drop for QVector<T>
57where
58    T: QVectorElement,
59{
60    /// Destroys the QVector.
61    fn drop(&mut self) {
62        T::drop(self);
63    }
64}
65
66impl<T> PartialEq for QVector<T>
67where
68    T: QVectorElement + PartialEq,
69{
70    /// Returns true if both vectors contain the same elements in the same order
71    fn eq(&self, other: &Self) -> bool {
72        self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
73    }
74}
75
76impl<T> Eq for QVector<T> where T: QVectorElement + Eq {}
77
78impl<T> QVector<T>
79where
80    T: QVectorElement,
81{
82    /// Inserts value at the end of the vector.
83    ///
84    /// The value is a reference here so it can be opaque or trivial but
85    /// note that the value is copied when being appended into the vector.
86    pub fn append_clone(&mut self, value: &T) {
87        T::append_clone(self, value);
88    }
89
90    /// Removes all elements from the vector.
91    pub fn clear(&mut self) {
92        T::clear(self);
93    }
94
95    /// Returns true if the vector contains item value; otherwise returns false.
96    pub fn contains(&self, value: &T) -> bool {
97        T::contains(self, value)
98    }
99
100    /// Returns the item at index position in the vector.
101    ///
102    /// index must be a valid position in the vector (i.e., 0 <= index < len()).
103    pub fn get(&self, index: isize) -> Option<&T> {
104        if index >= 0 && index < self.len() {
105            Some(unsafe { T::get_unchecked(self, index) })
106        } else {
107            None
108        }
109    }
110
111    /// Returns the index position of the first occurrence of value in the vector,
112    /// searching forward from index position from. Returns -1 if no item matched.
113    pub fn index_of(&self, value: &T) -> isize {
114        T::index_of(self, value)
115    }
116
117    /// Inserts item value into the vector at the given position.
118    ///
119    /// The value is a reference here so it can be opaque or trivial but
120    /// note that the value is copied when being inserted into the vector.
121    pub fn insert_clone(&mut self, pos: isize, value: &T) {
122        T::insert_clone(self, pos, value);
123    }
124
125    /// Returns true if the vector contains no elements; otherwise returns false.
126    pub fn is_empty(&self) -> bool {
127        T::len(self) == 0
128    }
129
130    /// An iterator visiting all elements in arbitrary order.
131    /// The iterator element type is &'a T.
132    pub fn iter(&self) -> Iter<'_, T> {
133        Iter {
134            vector: self,
135            index: 0,
136        }
137    }
138
139    /// Returns the number of items in the vector.
140    pub fn len(&self) -> isize {
141        T::len(self)
142    }
143
144    /// Reserve the specified capacity to prevent repeated allocations
145    /// when the maximum size is known.
146    pub fn reserve(&mut self, size: isize) {
147        T::reserve(self, size);
148    }
149
150    /// Removes the element at index position.
151    pub fn remove(&mut self, pos: isize) {
152        T::remove(self, pos);
153    }
154}
155
156impl<T> QVector<T>
157where
158    T: QVectorElement + ExternType<Kind = cxx::kind::Trivial>,
159{
160    /// Inserts value at the end of the vector.
161    pub fn append(&mut self, value: T) {
162        T::append(self, value);
163    }
164
165    /// Inserts item value into the vector at the given position.
166    pub fn insert(&mut self, pos: isize, value: T) {
167        T::insert(self, pos, value);
168    }
169}
170
171impl<T> From<&QVector<T>> for Vec<T>
172where
173    T: QVectorElement + Clone,
174{
175    /// Convert a reference to a [QVector] into a [Vec] by making a deep copy of the data.
176    /// The original QVector can still be used after constructing the Vec.
177    fn from(qvec: &QVector<T>) -> Self {
178        let mut vec = Vec::with_capacity(qvec.len().try_into().unwrap());
179        for element in qvec.iter() {
180            vec.push(element.clone());
181        }
182        vec
183    }
184}
185
186impl<T, S> From<S> for QVector<T>
187where
188    T: QVectorElement + Clone,
189    S: AsRef<[T]>,
190{
191    /// Convert anything that can be cheaply converted to a slice, such as an [array] or [Vec], into a [QVector]
192    /// by making a deep copy of the data.
193    /// The original slice can still be used after constructing the QVector.
194    fn from(vec: S) -> Self {
195        let mut qvec = Self::default();
196        qvec.reserve(vec.as_ref().len().try_into().unwrap());
197        for element in vec.as_ref() {
198            qvec.append_clone(element);
199        }
200        qvec
201    }
202}
203
204unsafe impl<T> ExternType for QVector<T>
205where
206    T: ExternType + QVectorElement,
207{
208    type Id = T::TypeId;
209    type Kind = cxx::kind::Trivial;
210}
211
212pub struct Iter<'a, T>
213where
214    T: QVectorElement,
215{
216    vector: &'a QVector<T>,
217    index: isize,
218}
219
220impl<'a, T> Iterator for Iter<'a, T>
221where
222    T: QVectorElement,
223{
224    type Item = &'a T;
225
226    fn next(&mut self) -> Option<Self::Item> {
227        if self.index < self.vector.len() {
228            let next = unsafe { T::get_unchecked(self.vector, self.index) };
229            self.index += 1;
230            Some(next)
231        } else {
232            None
233        }
234    }
235
236    fn size_hint(&self) -> (usize, Option<usize>) {
237        let len = self.len();
238        (len, Some(len))
239    }
240}
241
242impl<T> ExactSizeIterator for Iter<'_, T>
243where
244    T: QVectorElement,
245{
246    fn len(&self) -> usize {
247        (self.vector.len() - self.index) as usize
248    }
249}
250
251/// Trait implementation for an element in a [`QVector`].
252pub trait QVectorElement: Sized {
253    type TypeId;
254
255    fn append(vector: &mut QVector<Self>, value: Self)
256    where
257        Self: ExternType<Kind = cxx::kind::Trivial>;
258    fn append_clone(vector: &mut QVector<Self>, value: &Self);
259    fn clear(vector: &mut QVector<Self>);
260    fn clone(vector: &QVector<Self>) -> QVector<Self>;
261    fn contains(vector: &QVector<Self>, value: &Self) -> bool;
262    fn default() -> QVector<Self>;
263    fn drop(vector: &mut QVector<Self>);
264    /// # Safety
265    ///
266    /// Calling this method with an out-of-bounds index is undefined behavior
267    /// even if the resulting reference is not used.
268    unsafe fn get_unchecked(vector: &QVector<Self>, pos: isize) -> &Self;
269    fn index_of(vector: &QVector<Self>, value: &Self) -> isize;
270    fn insert(vector: &mut QVector<Self>, pos: isize, value: Self)
271    where
272        Self: ExternType<Kind = cxx::kind::Trivial>;
273    fn insert_clone(vector: &mut QVector<Self>, pos: isize, value: &Self);
274    fn len(vector: &QVector<Self>) -> isize;
275    fn remove(vector: &mut QVector<Self>, pos: isize);
276    fn reserve(vector: &mut QVector<Self>, size: isize);
277}
278
279macro_rules! impl_qvector_element {
280    ( $typeName:ty, $module:ident, $typeId:literal ) => {
281        mod $module;
282
283        impl QVectorElement for $typeName {
284            type TypeId = type_id!($typeId);
285
286            fn append(vector: &mut QVector<Self>, value: Self) {
287                $module::append(vector, &value);
288            }
289
290            fn append_clone(vector: &mut QVector<Self>, value: &Self) {
291                $module::append(vector, value);
292            }
293
294            fn clear(vector: &mut QVector<Self>) {
295                vector.cxx_clear()
296            }
297
298            fn clone(vector: &QVector<Self>) -> QVector<Self> {
299                $module::clone(vector)
300            }
301
302            fn contains(vector: &QVector<Self>, value: &Self) -> bool {
303                vector.cxx_contains(value)
304            }
305
306            fn default() -> QVector<Self> {
307                $module::default()
308            }
309
310            fn drop(vector: &mut QVector<Self>) {
311                $module::drop(vector);
312            }
313
314            unsafe fn get_unchecked(vector: &QVector<Self>, pos: isize) -> &Self {
315                $module::get_unchecked(vector, pos)
316            }
317
318            fn index_of(vector: &QVector<Self>, value: &Self) -> isize {
319                $module::index_of(vector, value)
320            }
321
322            fn insert(vector: &mut QVector<Self>, pos: isize, value: Self) {
323                $module::insert(vector, pos, &value);
324            }
325
326            fn insert_clone(vector: &mut QVector<Self>, pos: isize, value: &Self) {
327                $module::insert(vector, pos, value);
328            }
329
330            fn len(vector: &QVector<Self>) -> isize {
331                $module::len(vector)
332            }
333
334            fn remove(vector: &mut QVector<Self>, pos: isize) {
335                $module::remove(vector, pos);
336            }
337
338            fn reserve(vector: &mut QVector<Self>, size: isize) {
339                $module::reserve(vector, size);
340            }
341        }
342    };
343}
344
345impl_qvector_element!(bool, qvector_bool, "QVector_bool");
346impl_qvector_element!(f32, qvector_f32, "QVector_f32");
347impl_qvector_element!(f64, qvector_f64, "QVector_f64");
348impl_qvector_element!(i8, qvector_i8, "QVector_i8");
349impl_qvector_element!(i16, qvector_i16, "QVector_i16");
350impl_qvector_element!(i32, qvector_i32, "QVector_i32");
351impl_qvector_element!(i64, qvector_i64, "QVector_i64");
352impl_qvector_element!(QByteArray, qvector_qbytearray, "QVector_QByteArray");
353#[cfg(feature = "qt_gui")]
354impl_qvector_element!(QColor, qvector_qcolor, "QVector_QColor");
355impl_qvector_element!(QDate, qvector_qdate, "QVector_QDate");
356#[cfg(not(target_os = "emscripten"))]
357impl_qvector_element!(QDateTime, qvector_qdatetime, "QVector_QDateTime");
358impl_qvector_element!(QLine, qvector_qline, "QVector_QLine");
359impl_qvector_element!(QLineF, qvector_qlinef, "QVector_QLineF");
360impl_qvector_element!(QMargins, qvector_qmargins, "QVector_QMargins");
361impl_qvector_element!(QMarginsF, qvector_qmarginsf, "QVector_QMarginsF");
362impl_qvector_element!(
363    QPersistentModelIndex,
364    qvector_qpersistentmodelindex,
365    "QVector_QPersistentModelIndex"
366);
367impl_qvector_element!(QPoint, qvector_qpoint, "QVector_QPoint");
368impl_qvector_element!(QPointF, qvector_qpointf, "QVector_QPointF");
369impl_qvector_element!(QRect, qvector_qrect, "QVector_QRect");
370impl_qvector_element!(QRectF, qvector_qrectf, "QVector_QRectF");
371impl_qvector_element!(QSize, qvector_qsize, "QVector_QSize");
372impl_qvector_element!(QSizeF, qvector_qsizef, "QVector_QSizeF");
373impl_qvector_element!(QString, qvector_qstring, "QVector_QString");
374impl_qvector_element!(QTime, qvector_qtime, "QVector_QTime");
375impl_qvector_element!(QUrl, qvector_qurl, "QVector_QUrl");
376impl_qvector_element!(QVariant, qvector_qvariant, "QVector_QVariant");
377impl_qvector_element!(u8, qvector_u8, "QVector_u8");
378impl_qvector_element!(u16, qvector_u16, "QVector_u16");
379impl_qvector_element!(u32, qvector_u32, "QVector_u32");
380impl_qvector_element!(u64, qvector_u64, "QVector_u64");
381
382#[cfg(test)]
383mod test {
384    use super::*;
385
386    #[test]
387    fn qvec_from_array_to_vec() {
388        let array = [0, 1, 2];
389        let qvec = QVector::<u8>::from(array);
390        assert_eq!(Vec::from(&qvec), array);
391    }
392}