Skip to content

Commit 358748d

Browse files
authored
Implement FromIterator for QList, QSet, and QVector (#1269)
* cxx-qt-lib: implement FromIterator for QList * cxx-qt-lib: implement FromIterator for QSet * cxx-qt-lib: implement FromIterator for QVector * cxx-qt-lib: reserve_usize helper functions * cxx-qt-lib: use isize::MAX if reserve is called with excessive value
1 parent 82b97ef commit 358748d

File tree

4 files changed

+180
-27
lines changed

4 files changed

+180
-27
lines changed

crates/cxx-qt-lib/src/core/qlist/mod.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,28 @@ where
161161
pub fn reserve(&mut self, size: isize) {
162162
T::reserve(self, size);
163163
}
164+
165+
/// Helper function for handling Rust values.
166+
pub(crate) fn reserve_usize(&mut self, size: usize) {
167+
if size != 0 {
168+
T::reserve(self, isize::try_from(size).unwrap_or(isize::MAX));
169+
}
170+
}
171+
}
172+
173+
impl<T> QList<T>
174+
where
175+
T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
176+
{
177+
/// Inserts value at the end of the list.
178+
pub fn append(&mut self, value: T) {
179+
T::append(self, value);
180+
}
181+
182+
/// Inserts item value into the list at the given position.
183+
pub fn insert(&mut self, pos: isize, value: T) {
184+
T::insert(self, pos, value);
185+
}
164186
}
165187

166188
impl<T> From<&QList<T>> for Vec<T>
@@ -188,26 +210,59 @@ where
188210
/// The original slice can still be used after constructing the QList.
189211
fn from(vec: S) -> Self {
190212
let mut qlist = Self::default();
191-
qlist.reserve(vec.as_ref().len().try_into().unwrap());
213+
qlist.reserve_usize(vec.as_ref().len());
192214
for element in vec.as_ref() {
193215
qlist.append_clone(element);
194216
}
195217
qlist
196218
}
197219
}
198220

199-
impl<T> QList<T>
221+
impl<'a, T> Extend<&'a T> for QList<T>
222+
where
223+
T: QListElement,
224+
{
225+
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
226+
let iter = iter.into_iter();
227+
self.reserve_usize(iter.size_hint().0);
228+
for element in iter {
229+
self.append_clone(element);
230+
}
231+
}
232+
}
233+
234+
impl<T> Extend<T> for QList<T>
200235
where
201236
T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
202237
{
203-
/// Inserts value at the end of the list.
204-
pub fn append(&mut self, value: T) {
205-
T::append(self, value);
238+
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
239+
let iter = iter.into_iter();
240+
self.reserve_usize(iter.size_hint().0);
241+
for element in iter {
242+
self.append(element);
243+
}
206244
}
245+
}
207246

208-
/// Inserts item value into the list at the given position.
209-
pub fn insert(&mut self, pos: isize, value: T) {
210-
T::insert(self, pos, value);
247+
impl<'a, T> FromIterator<&'a T> for QList<T>
248+
where
249+
T: QListElement,
250+
{
251+
fn from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Self {
252+
let mut qlist = Self::default();
253+
qlist.extend(iter);
254+
qlist
255+
}
256+
}
257+
258+
impl<T> FromIterator<T> for QList<T>
259+
where
260+
T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
261+
{
262+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
263+
let mut qlist = Self::default();
264+
qlist.extend(iter);
265+
qlist
211266
}
212267
}
213268

crates/cxx-qt-lib/src/core/qset/mod.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ where
127127
pub fn reserve(&mut self, size: isize) {
128128
T::reserve(self, size);
129129
}
130+
131+
/// Helper function for handling Rust values.
132+
pub(crate) fn reserve_usize(&mut self, size: usize) {
133+
if size != 0 {
134+
T::reserve(self, isize::try_from(size).unwrap_or(isize::MAX));
135+
}
136+
}
130137
}
131138

132139
impl<T> QSet<T>
@@ -140,6 +147,54 @@ where
140147
}
141148
}
142149

150+
impl<'a, T> Extend<&'a T> for QSet<T>
151+
where
152+
T: QSetElement,
153+
{
154+
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
155+
let iter = iter.into_iter();
156+
self.reserve_usize(iter.size_hint().0);
157+
for element in iter {
158+
self.insert_clone(element);
159+
}
160+
}
161+
}
162+
163+
impl<T> Extend<T> for QSet<T>
164+
where
165+
T: QSetElement + ExternType<Kind = cxx::kind::Trivial>,
166+
{
167+
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
168+
let iter = iter.into_iter();
169+
self.reserve_usize(iter.size_hint().0);
170+
for element in iter {
171+
self.insert(element);
172+
}
173+
}
174+
}
175+
176+
impl<'a, T> FromIterator<&'a T> for QSet<T>
177+
where
178+
T: QSetElement,
179+
{
180+
fn from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Self {
181+
let mut qset = Self::default();
182+
qset.extend(iter);
183+
qset
184+
}
185+
}
186+
187+
impl<T> FromIterator<T> for QSet<T>
188+
where
189+
T: QSetElement + ExternType<Kind = cxx::kind::Trivial>,
190+
{
191+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
192+
let mut qset = Self::default();
193+
qset.extend(iter);
194+
qset
195+
}
196+
}
197+
143198
unsafe impl<T> ExternType for QSet<T>
144199
where
145200
T: ExternType + QSetElement,

crates/cxx-qt-lib/src/core/qvector/mod.rs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,22 @@ where
151151
T::len(self)
152152
}
153153

154+
/// Removes the element at index position.
155+
pub fn remove(&mut self, pos: isize) {
156+
T::remove(self, pos);
157+
}
158+
154159
/// Reserve the specified capacity to prevent repeated allocations
155160
/// when the maximum size is known.
156161
pub fn reserve(&mut self, size: isize) {
157162
T::reserve(self, size);
158163
}
159164

160-
/// Removes the element at index position.
161-
pub fn remove(&mut self, pos: isize) {
162-
T::remove(self, pos);
165+
/// Helper function for handling Rust values.
166+
pub(crate) fn reserve_usize(&mut self, size: usize) {
167+
if size != 0 {
168+
T::reserve(self, isize::try_from(size).unwrap_or(isize::MAX));
169+
}
163170
}
164171
}
165172

@@ -203,13 +210,60 @@ where
203210
/// The original slice can still be used after constructing the QVector.
204211
fn from(vec: S) -> Self {
205212
let mut qvec = Self::default();
206-
qvec.reserve(vec.as_ref().len().try_into().unwrap());
213+
qvec.reserve_usize(vec.as_ref().len());
207214
for element in vec.as_ref() {
208215
qvec.append_clone(element);
209216
}
210217
qvec
211218
}
212219
}
220+
impl<'a, T> Extend<&'a T> for QVector<T>
221+
where
222+
T: QVectorElement,
223+
{
224+
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
225+
let iter = iter.into_iter();
226+
self.reserve_usize(iter.size_hint().0);
227+
for element in iter {
228+
self.append_clone(element);
229+
}
230+
}
231+
}
232+
233+
impl<T> Extend<T> for QVector<T>
234+
where
235+
T: QVectorElement + ExternType<Kind = cxx::kind::Trivial>,
236+
{
237+
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
238+
let iter = iter.into_iter();
239+
self.reserve_usize(iter.size_hint().0);
240+
for element in iter {
241+
self.append(element);
242+
}
243+
}
244+
}
245+
246+
impl<'a, T> FromIterator<&'a T> for QVector<T>
247+
where
248+
T: QVectorElement,
249+
{
250+
fn from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Self {
251+
let mut qlist = Self::default();
252+
qlist.extend(iter);
253+
qlist
254+
}
255+
}
256+
257+
impl<T> FromIterator<T> for QVector<T>
258+
where
259+
T: QVectorElement + ExternType<Kind = cxx::kind::Trivial>,
260+
{
261+
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
262+
let mut qlist = Self::default();
263+
qlist.extend(iter);
264+
qlist
265+
}
266+
}
213267

214268
unsafe impl<T> ExternType for QVector<T>
215269
where

crates/cxx-qt-lib/src/serde_impl.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,6 @@ use serde::de::{SeqAccess, Visitor};
88
use serde::{Deserialize, Deserializer, Serialize, Serializer};
99
use std::fmt::{self, Formatter};
1010
use std::marker::PhantomData;
11-
use std::num::NonZeroIsize;
12-
13-
/// Serde deserializers provide an `Option<usize>` size hint, but Qt containers use signed types
14-
/// for size. This helper function converts between the two.
15-
/// It also returns `None` if the size hint is 0, because there's no need to reserve capacity of 0.
16-
const fn get_size_hint(size_hint: Option<usize>) -> Option<NonZeroIsize> {
17-
match size_hint {
18-
Some(n) if n <= isize::MAX as usize => NonZeroIsize::new(n as isize),
19-
_ => None,
20-
}
21-
}
2211

2312
/// Serializes and deserializes a list-like container by iterating over values.
2413
macro_rules! seq_impl {
@@ -57,8 +46,8 @@ macro_rules! seq_impl {
5746
A: SeqAccess<'de>,
5847
{
5948
let mut values = Self::Value::default();
60-
if let Some(size_hint) = get_size_hint(seq.size_hint()) {
61-
values.reserve(size_hint.get());
49+
if let Some(size_hint) = seq.size_hint() {
50+
values.reserve_usize(size_hint);
6251
}
6352
while let Some(value) = seq.next_element()? {
6453
$insert(&mut values, value);
@@ -107,8 +96,8 @@ macro_rules! deref_impl {
10796
{
10897
let mut list = Self::Value::default();
10998
let values = &mut *list;
110-
if let Some(size_hint) = get_size_hint(seq.size_hint()) {
111-
values.reserve(size_hint.get());
99+
if let Some(size_hint) = seq.size_hint() {
100+
values.reserve_usize(size_hint);
112101
}
113102
while let Some(value) = seq.next_element()? {
114103
values.append(value);

0 commit comments

Comments
 (0)