mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Fix SharedVector creation from iterators with default size hints
* In capacity_for_grow, don't compare the number of elements (current_cap) with the size of an element in bytes, but with the required capacity instead (to detect that we don't need to grow). Not all call sites check for that (i.e. push), so there's a new test for that. * When re-allocating due to growth and copying elements from the old inner to the new inner, make sure to copy all old elements from the beginning, not only the last element repeatedly.
This commit is contained in:
parent
c8e96f60b0
commit
b4ba77dba7
2 changed files with 46 additions and 2 deletions
|
@ -65,7 +65,7 @@ fn alloc_with_capacity<T>(capacity: usize) -> NonNull<SharedVectorInner<T>> {
|
|||
/// Return a new capacity suitable for this vector
|
||||
/// Loosely based on alloc::raw_vec::RawVec::grow_amortized.
|
||||
fn capacity_for_grow(current_cap: usize, required_cap: usize, elem_size: usize) -> usize {
|
||||
if current_cap >= elem_size {
|
||||
if current_cap >= required_cap {
|
||||
return current_cap;
|
||||
}
|
||||
let cap = core::cmp::max(current_cap * 2, required_cap);
|
||||
|
@ -315,7 +315,7 @@ impl<T> FromIterator<T> for SharedVector<T> {
|
|||
while *begin < size {
|
||||
unsafe {
|
||||
core::ptr::write(
|
||||
result.inner.as_mut().data.as_mut_ptr().add(size),
|
||||
result.inner.as_mut().data.as_mut_ptr().add(*begin),
|
||||
core::ptr::read(old_inner.as_ref().data.as_ptr().add(*begin)),
|
||||
);
|
||||
*begin += 1;
|
||||
|
@ -483,6 +483,49 @@ fn invalid_capacity_test() {
|
|||
let _: SharedVector<u8> = SharedVector::with_capacity(usize::MAX / 2 - 1000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_from_iter_with_no_size_hint() {
|
||||
struct NoSizeHintIter<'a> {
|
||||
data: &'a [&'a str],
|
||||
i: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for NoSizeHintIter<'a> {
|
||||
type Item = String;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.i >= self.data.len() {
|
||||
return None;
|
||||
}
|
||||
let item = self.data[self.i];
|
||||
self.i += 1;
|
||||
Some(item.to_string())
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, None)
|
||||
}
|
||||
}
|
||||
|
||||
// 5 elements to be above the initial "grow"-capacity of 4 and thus require one realloc.
|
||||
let input = NoSizeHintIter { data: &["Hello", "sweet", "world", "of", "iterators"], i: 0 };
|
||||
|
||||
let shared_vec: SharedVector<String> = input.collect();
|
||||
assert_eq!(shared_vec.as_slice(), &["Hello", "sweet", "world", "of", "iterators"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_capacity_grows_only_when_needed() {
|
||||
let mut vec: SharedVector<u8> = SharedVector::with_capacity(2);
|
||||
vec.push(0);
|
||||
assert_eq!(vec.capacity(), 2);
|
||||
vec.push(0);
|
||||
assert_eq!(vec.capacity(), 2);
|
||||
vec.push(0);
|
||||
assert_eq!(vec.len(), 3);
|
||||
assert!(vec.capacity() > 2);
|
||||
}
|
||||
|
||||
#[cfg(feature = "ffi")]
|
||||
pub(crate) mod ffi {
|
||||
use super::*;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue