1#[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, QUuid, QVariant,
13};
14use core::{marker::PhantomData, mem::MaybeUninit};
15use cxx::{type_id, ExternType};
16use std::fmt;
17
18#[repr(C)]
24pub struct QList<T>
25where
26 T: QListElement,
27{
28 #[cfg(cxxqt_qt_version_major = "5")]
33 _space: MaybeUninit<usize>,
34 #[cfg(cxxqt_qt_version_major = "6")]
35 _space: MaybeUninit<[usize; 3]>,
36 _value: PhantomData<T>,
37}
38
39impl<T> Clone for QList<T>
40where
41 T: QListElement,
42{
43 fn clone(&self) -> Self {
45 T::clone(self)
46 }
47}
48
49impl<T> Default for QList<T>
50where
51 T: QListElement,
52{
53 fn default() -> Self {
55 T::default()
56 }
57}
58
59impl<T> Drop for QList<T>
60where
61 T: QListElement,
62{
63 fn drop(&mut self) {
65 T::drop(self);
66 }
67}
68
69impl<T> PartialEq for QList<T>
70where
71 T: QListElement + PartialEq,
72{
73 fn eq(&self, other: &Self) -> bool {
75 self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
76 }
77}
78
79impl<T> Eq for QList<T> where T: QListElement + Eq {}
80
81impl<T> fmt::Debug for QList<T>
82where
83 T: QListElement + fmt::Debug,
84{
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 f.debug_list().entries(self.iter()).finish()
87 }
88}
89
90impl<T> QList<T>
91where
92 T: QListElement,
93{
94 pub fn append_clone(&mut self, value: &T) {
99 T::append_clone(self, value);
100 }
101
102 pub fn clear(&mut self) {
106 T::clear(self);
107 }
108
109 pub fn contains(&self, value: &T) -> bool {
111 T::contains(self, value)
112 }
113
114 pub fn get(&self, index: isize) -> Option<&T> {
116 if index >= 0 && index < self.len() {
117 Some(unsafe { T::get_unchecked(self, index) })
118 } else {
119 None
120 }
121 }
122
123 pub fn index_of(&self, value: &T) -> isize {
125 T::index_of(self, value)
126 }
127
128 pub fn insert_clone(&mut self, pos: isize, value: &T) {
133 T::insert_clone(self, pos, value);
134 }
135
136 pub fn is_empty(&self) -> bool {
138 T::len(self) == 0
139 }
140
141 pub fn iter(&self) -> Iter<'_, T> {
144 Iter {
145 list: self,
146 index: 0,
147 }
148 }
149
150 pub fn len(&self) -> isize {
152 T::len(self)
153 }
154
155 pub fn remove(&mut self, pos: isize) {
159 T::remove(self, pos);
160 }
161
162 pub fn reserve(&mut self, size: isize) {
168 T::reserve(self, size);
169 }
170
171 pub(crate) fn reserve_usize(&mut self, size: usize) {
173 if size != 0 {
174 T::reserve(self, isize::try_from(size).unwrap_or(isize::MAX));
175 }
176 }
177}
178
179impl<T> QList<T>
180where
181 T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
182{
183 pub fn append(&mut self, value: T) {
185 T::append(self, value);
186 }
187
188 pub fn insert(&mut self, pos: isize, value: T) {
190 T::insert(self, pos, value);
191 }
192}
193
194impl<T> From<&QList<T>> for Vec<T>
195where
196 T: QListElement + Clone,
197{
198 fn from(qlist: &QList<T>) -> Self {
201 let mut vec = Vec::with_capacity(qlist.len().try_into().unwrap());
202 for element in qlist.iter() {
203 vec.push(element.clone());
204 }
205 vec
206 }
207}
208
209impl<T, S> From<S> for QList<T>
210where
211 T: QListElement + Clone,
212 S: AsRef<[T]>,
213{
214 fn from(vec: S) -> Self {
218 let mut qlist = Self::default();
219 qlist.reserve_usize(vec.as_ref().len());
220 for element in vec.as_ref() {
221 qlist.append_clone(element);
222 }
223 qlist
224 }
225}
226
227impl<'a, T> Extend<&'a T> for QList<T>
228where
229 T: QListElement,
230{
231 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
232 let iter = iter.into_iter();
233 self.reserve_usize(iter.size_hint().0);
234 for element in iter {
235 self.append_clone(element);
236 }
237 }
238}
239
240impl<T> Extend<T> for QList<T>
241where
242 T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
243{
244 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
245 let iter = iter.into_iter();
246 self.reserve_usize(iter.size_hint().0);
247 for element in iter {
248 self.append(element);
249 }
250 }
251}
252
253impl<'a, T> FromIterator<&'a T> for QList<T>
254where
255 T: QListElement,
256{
257 fn from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Self {
258 let mut qlist = Self::default();
259 qlist.extend(iter);
260 qlist
261 }
262}
263
264impl<T> FromIterator<T> for QList<T>
265where
266 T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
267{
268 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
269 let mut qlist = Self::default();
270 qlist.extend(iter);
271 qlist
272 }
273}
274
275unsafe impl<T> ExternType for QList<T>
276where
277 T: ExternType + QListElement,
278{
279 type Id = T::TypeId;
280 type Kind = cxx::kind::Trivial;
281}
282
283pub struct Iter<'a, T>
284where
285 T: QListElement,
286{
287 list: &'a QList<T>,
288 index: isize,
289}
290
291impl<'a, T> Iterator for Iter<'a, T>
292where
293 T: QListElement,
294{
295 type Item = &'a T;
296
297 fn next(&mut self) -> Option<Self::Item> {
298 if self.index < self.list.len() {
299 let next = unsafe { T::get_unchecked(self.list, self.index) };
300 self.index += 1;
301 Some(next)
302 } else {
303 None
304 }
305 }
306
307 fn size_hint(&self) -> (usize, Option<usize>) {
308 let len = self.len();
309 (len, Some(len))
310 }
311}
312
313impl<T> ExactSizeIterator for Iter<'_, T>
314where
315 T: QListElement,
316{
317 fn len(&self) -> usize {
318 (self.list.len() - self.index) as usize
319 }
320}
321
322impl<'a, T> IntoIterator for &'a QList<T>
323where
324 T: QListElement,
325{
326 type Item = &'a T;
327
328 type IntoIter = Iter<'a, T>;
329
330 fn into_iter(self) -> Self::IntoIter {
331 self.iter()
332 }
333}
334
335pub trait QListElement: Sized {
337 type TypeId;
338
339 fn append(list: &mut QList<Self>, value: Self)
340 where
341 Self: ExternType<Kind = cxx::kind::Trivial>;
342 fn append_clone(list: &mut QList<Self>, value: &Self);
343 fn clear(list: &mut QList<Self>);
344 fn clone(list: &QList<Self>) -> QList<Self>;
345 fn contains(list: &QList<Self>, value: &Self) -> bool;
346 fn default() -> QList<Self>;
347 fn drop(list: &mut QList<Self>);
348 unsafe fn get_unchecked(list: &QList<Self>, pos: isize) -> &Self;
353 fn index_of(list: &QList<Self>, value: &Self) -> isize;
354 fn insert(list: &mut QList<Self>, pos: isize, value: Self)
355 where
356 Self: ExternType<Kind = cxx::kind::Trivial>;
357 fn insert_clone(list: &mut QList<Self>, pos: isize, value: &Self);
358 fn len(list: &QList<Self>) -> isize;
359 fn remove(list: &mut QList<Self>, pos: isize);
360 fn reserve(vector: &mut QList<Self>, size: isize);
361}
362
363macro_rules! impl_qlist_element {
364 ( $typeName:ty, $module:ident, $typeId:literal ) => {
365 mod $module;
366
367 impl QListElement for $typeName {
368 type TypeId = type_id!($typeId);
369
370 fn append(list: &mut QList<Self>, value: Self) {
371 $module::append(list, &value);
372 }
373
374 fn append_clone(list: &mut QList<Self>, value: &Self) {
375 $module::append(list, value);
376 }
377
378 fn clear(list: &mut QList<Self>) {
379 list.cxx_clear()
380 }
381
382 fn clone(list: &QList<Self>) -> QList<Self> {
383 $module::clone(list)
384 }
385
386 fn contains(list: &QList<Self>, value: &Self) -> bool {
387 list.cxx_contains(value)
388 }
389
390 fn default() -> QList<Self> {
391 $module::default()
392 }
393
394 fn drop(list: &mut QList<Self>) {
395 $module::drop(list);
396 }
397
398 unsafe fn get_unchecked(list: &QList<Self>, pos: isize) -> &Self {
399 $module::get_unchecked(list, pos)
400 }
401
402 fn index_of(list: &QList<Self>, value: &Self) -> isize {
403 $module::index_of(list, value)
404 }
405
406 fn insert(list: &mut QList<Self>, pos: isize, value: Self) {
407 $module::insert(list, pos, &value);
408 }
409
410 fn insert_clone(list: &mut QList<Self>, pos: isize, value: &Self) {
411 $module::insert(list, pos, value);
412 }
413
414 fn len(list: &QList<Self>) -> isize {
415 $module::len(list)
416 }
417
418 fn remove(list: &mut QList<Self>, pos: isize) {
419 $module::remove(list, pos);
420 }
421
422 fn reserve(list: &mut QList<Self>, size: isize) {
423 $module::reserve(list, size);
424 }
425 }
426 };
427}
428
429impl_qlist_element!(bool, qlist_bool, "QList_bool");
430impl_qlist_element!(f32, qlist_f32, "QList_f32");
431impl_qlist_element!(f64, qlist_f64, "QList_f64");
432impl_qlist_element!(i8, qlist_i8, "QList_i8");
433impl_qlist_element!(i16, qlist_i16, "QList_i16");
434impl_qlist_element!(i32, qlist_i32, "QList_i32");
435impl_qlist_element!(i64, qlist_i64, "QList_i64");
436impl_qlist_element!(QByteArray, qlist_qbytearray, "QList_QByteArray");
437#[cfg(feature = "qt_gui")]
438impl_qlist_element!(QColor, qlist_qcolor, "QList_QColor");
439impl_qlist_element!(QDate, qlist_qdate, "QList_QDate");
440#[cfg(not(target_os = "emscripten"))]
441impl_qlist_element!(QDateTime, qlist_qdatetime, "QList_QDateTime");
442impl_qlist_element!(QLine, qlist_qline, "QList_QLine");
443impl_qlist_element!(QLineF, qlist_qlinef, "QList_QLineF");
444impl_qlist_element!(QMargins, qlist_qmargins, "QList_QMargins");
445impl_qlist_element!(QMarginsF, qlist_qmarginsf, "QList_QMarginsF");
446impl_qlist_element!(
447 QPersistentModelIndex,
448 qlist_qpersistentmodelindex,
449 "QList_QPersistentModelIndex"
450);
451impl_qlist_element!(QPoint, qlist_qpoint, "QList_QPoint");
452impl_qlist_element!(QPointF, qlist_qpointf, "QList_QPointF");
453impl_qlist_element!(QRect, qlist_qrect, "QList_QRect");
454impl_qlist_element!(QRectF, qlist_qrectf, "QList_QRectF");
455impl_qlist_element!(QSize, qlist_qsize, "QList_QSize");
456impl_qlist_element!(QSizeF, qlist_qsizef, "QList_QSizeF");
457impl_qlist_element!(QString, qlist_qstring, "QList_QString");
458impl_qlist_element!(QTime, qlist_qtime, "QList_QTime");
459impl_qlist_element!(QUrl, qlist_qurl, "QList_QUrl");
460impl_qlist_element!(QUuid, qlist_quuid, "QList_QUuid");
461impl_qlist_element!(QVariant, qlist_qvariant, "QList_QVariant");
462impl_qlist_element!(u8, qlist_u8, "QList_u8");
463impl_qlist_element!(u16, qlist_u16, "QList_u16");
464impl_qlist_element!(u32, qlist_u32, "QList_u32");
465impl_qlist_element!(u64, qlist_u64, "QList_u64");
466
467#[cfg(test)]
468mod test {
469 use super::*;
470
471 #[test]
472 fn qlist_from_array_to_vec() {
473 let array = [0, 1, 2];
474 let qlist = QList::<u8>::from(array);
475 assert_eq!(Vec::from(&qlist), array);
476 }
477
478 #[cfg(feature = "serde")]
479 #[test]
480 fn qlist_serde() {
481 let qlist = QList::<u8>::from([0, 1, 2]);
482 assert_eq!(crate::serde_impl::roundtrip(&qlist), qlist);
483 }
484}