Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: coverage

on:
workflow_dispatch:
push:
branches: [ main, dev ]
pull_request:
branches: [ main, dev ]

jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install Rust
run: rustup update stable

- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov

- name: Generate code coverage
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
files: lcov.info
fail_ci_if_error: true
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.15.0
### Added
- `AnyVec` implements `Extend` now.
- `AnyVecTyped` implements `Extend` now.
- `AnyVec::append()` added.
- `AnyVecTyped::append()` added.

## 0.14.0
### Added
- Now library `no_std` friendly.
Expand Down
2 changes: 1 addition & 1 deletion src/any_value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ pub trait AnyValueCloneable: AnyValueSizeless {
unsafe fn clone_into(&self, out: *mut u8);

#[inline]
fn lazy_clone(&self) -> LazyClone<Self>
fn lazy_clone(&self) -> LazyClone<'_, Self>
where Self: Sized
{
LazyClone::new(self)
Expand Down
2 changes: 1 addition & 1 deletion src/any_value/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::any_value::{AnyValue, AnyValueMut, AnyValueTypelessMut, AnyValueTypel
/// special in any way.
///
/// [AnyValueRaw]: super::AnyValueRaw
#[derive(Debug)]
pub struct AnyValueWrapper<T: 'static>{
value: T
}
Expand All @@ -17,7 +18,6 @@ impl<T: 'static> AnyValueWrapper<T> {
Self{ value }
}
}

impl<T: 'static> AnyValueSizeless for AnyValueWrapper<T> {
type Type = T;

Expand Down
81 changes: 62 additions & 19 deletions src/any_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use core::ops::{Deref, DerefMut, Range, RangeBounds};
use core::ptr::NonNull;
use core::{fmt, ptr, slice};
use core::slice::{from_raw_parts, from_raw_parts_mut};
use crate::{AnyVecTyped, into_range, mem, ops};
use crate::any_value::{AnyValue, AnyValueSizeless};
use crate::{AnyVecTyped, into_range, mem, ops, assert_types_equal};
use crate::any_value::{AnyValue, AnyValueSizeless, Unknown};
use crate::any_vec_raw::{AnyVecRaw, DropFn};
use crate::ops::{TempValue, Remove, SwapRemove, remove, swap_remove, Pop, pop};
use crate::ops::{Drain, Splice, drain, splice};
Expand Down Expand Up @@ -423,7 +423,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// Returns [`AnyVecRef`] - typed view to const AnyVec,
/// if container holds elements of type T, or None if it isn’t.
#[inline]
pub fn downcast_ref<T: 'static>(&self) -> Option<AnyVecRef<T, M>> {
pub fn downcast_ref<T: 'static>(&self) -> Option<AnyVecRef<'_, T, M>> {
if self.element_typeid() == TypeId::of::<T>() {
unsafe{ Some(self.downcast_ref_unchecked()) }
} else {
Expand All @@ -438,14 +438,14 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// The container elements must be of type `T`.
/// Calling this method with the incorrect type is undefined behavior.
#[inline]
pub unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> AnyVecRef<T, M> {
pub unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> AnyVecRef<'_, T, M> {
AnyVecRef(AnyVecTyped::new(NonNull::from(&self.raw)))
}

/// Returns [`AnyVecMut`] - typed view to mut AnyVec,
/// if container holds elements of type T, or None if it isn’t.
#[inline]
pub fn downcast_mut<T: 'static>(&mut self) -> Option<AnyVecMut<T, M>> {
pub fn downcast_mut<T: 'static>(&mut self) -> Option<AnyVecMut<'_, T, M>> {
if self.element_typeid() == TypeId::of::<T>() {
unsafe{ Some(self.downcast_mut_unchecked()) }
} else {
Expand All @@ -460,7 +460,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// The container elements must be of type `T`.
/// Calling this method with the incorrect type is undefined behavior.
#[inline]
pub unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> AnyVecMut<T, M> {
pub unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> AnyVecMut<'_, T, M> {
AnyVecMut(AnyVecTyped::new(NonNull::from(&mut self.raw)))
}

Expand Down Expand Up @@ -489,12 +489,12 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
}

#[inline]
pub fn iter(&self) -> IterRef<Traits, M>{
pub fn iter(&self) -> IterRef<'_, Traits, M>{
Iter::new(AnyVecPtr::from(self), 0, self.len())
}

#[inline]
pub fn iter_mut(&mut self) -> IterMut<Traits, M>{
pub fn iter_mut(&mut self) -> IterMut<'_, Traits, M>{
let len = self.len();
Iter::new(AnyVecPtr::from(self), 0, len)
}
Expand All @@ -505,12 +505,12 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
///
/// * Panics if index is out of bounds.
#[inline]
pub fn at(&self, index: usize) -> ElementRef<Traits, M>{
pub fn at(&self, index: usize) -> ElementRef<'_, Traits, M>{
self.get(index).unwrap()
}

#[inline]
pub fn get(&self, index: usize) -> Option<ElementRef<Traits, M>>{
pub fn get(&self, index: usize) -> Option<ElementRef<'_, Traits, M>>{
if index < self.len(){
Some(unsafe{ self.get_unchecked(index) })
} else {
Expand All @@ -519,7 +519,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
}

#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> ElementRef<Traits, M>{
pub unsafe fn get_unchecked(&self, index: usize) -> ElementRef<'_, Traits, M>{
let element_ptr = self.raw.get_unchecked(index) as *mut u8;
ElementRef(
ManuallyDrop::new(ElementPointer::new(
Expand All @@ -535,12 +535,12 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
///
/// * Panics if index is out of bounds.
#[inline]
pub fn at_mut(&mut self, index: usize) -> ElementMut<Traits, M>{
pub fn at_mut(&mut self, index: usize) -> ElementMut<'_, Traits, M>{
self.get_mut(index).unwrap()
}

#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<ElementMut<Traits, M>>{
pub fn get_mut(&mut self, index: usize) -> Option<ElementMut<'_, Traits, M>>{
if index < self.len(){
Some(unsafe{ self.get_unchecked_mut(index) })
} else {
Expand All @@ -549,7 +549,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
}

#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> ElementMut<Traits, M> {
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> ElementMut<'_, Traits, M> {
let element_ptr = self.raw.get_unchecked_mut(index);
ElementMut(
ManuallyDrop::new(ElementPointer::new(
Expand Down Expand Up @@ -625,7 +625,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// [`mem::forget`]: core::mem::forget
///
#[inline]
pub fn pop(&mut self) -> Option<Pop<Traits, M>> {
pub fn pop(&mut self) -> Option<Pop<'_, Traits, M>> {
if self.is_empty(){
None
} else {
Expand All @@ -648,7 +648,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// [`mem::forget`]: core::mem::forget
///
#[inline]
pub fn remove(&mut self, index: usize) -> Remove<Traits, M> {
pub fn remove(&mut self, index: usize) -> Remove<'_, Traits, M> {
self.raw.index_check(index);
TempValue::new(remove::Remove::new(
AnyVecPtr::from(self),
Expand All @@ -669,13 +669,31 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// [`mem::forget`]: core::mem::forget
///
#[inline]
pub fn swap_remove(&mut self, index: usize) -> SwapRemove<Traits, M> {
pub fn swap_remove(&mut self, index: usize) -> SwapRemove<'_, Traits, M> {
self.raw.index_check(index);
TempValue::new(swap_remove::SwapRemove::new(
AnyVecPtr::from(self),
index
))
}

/// Moves all the elements of `other` into `self`, leaving `other` empty.
///
/// # Panics
///
/// * Panics if types mismatch.
/// * Panics if out of memory.
pub fn append<OtherTraits, OtherM>(
&mut self, other: &mut AnyVec<OtherTraits, OtherM>
) where
OtherTraits: ?Sized + Trait,
OtherM: MemBuilder
{
assert_types_equal(other.element_typeid(), self.element_typeid());
unsafe{
self.raw.append_unchecked::<Unknown, _>(&mut other.raw);
}
}

/// Removes the specified range from the vector in bulk, returning all removed
/// elements as an iterator. If the iterator is dropped before being fully consumed,
Expand All @@ -697,7 +715,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
/// [`mem::forget`]: core::mem::forget
///
#[inline]
pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<Traits, M> {
pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<'_, Traits, M> {
let Range{start, end} = into_range(self.len(), range);
ops::Iter(drain::Drain::new(
AnyVecPtr::from(self),
Expand Down Expand Up @@ -729,7 +747,7 @@ impl<Traits: ?Sized + Trait, M: MemBuilder> AnyVec<Traits, M>
///
#[inline]
pub fn splice<I: IntoIterator>(&mut self, range: impl RangeBounds<usize>, replace_with: I)
-> Splice<Traits, M, I::IntoIter>
-> Splice<'_, Traits, M, I::IntoIter>
where
I::IntoIter: ExactSizeIterator,
I::Item: AnyValue
Expand Down Expand Up @@ -813,6 +831,25 @@ impl<Traits: ?Sized + Cloneable + Trait, M: MemBuilder> Clone for AnyVec<Traits,
}
}

impl<Traits, M, A> Extend<A> for AnyVec<Traits, M>
where
Traits: ?Sized + Trait,
M: MemBuilder,
A: AnyValue,
{
/// # Panics
///
/// * Panics if type mismatch.
/// * Panics if out of memory.
fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
let iter = iter.into_iter();
self.raw.reserve(iter.size_hint().0);
for v in iter {
self.push(v);
}
}
}

impl<Traits: ?Sized + Trait, M: MemBuilder> Debug for AnyVec<Traits, M>{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("AnyVec")
Expand Down Expand Up @@ -912,4 +949,10 @@ impl<'a, T: 'static + Debug, M: MemBuilder + 'a> Debug for AnyVecMut<'a, T, M>{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<'a, T: 'static, M: MemBuilder + 'a> Extend<T> for AnyVecMut<'a, T, M>{
#[inline]
fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
self.0.extend(iter)
}
}
2 changes: 0 additions & 2 deletions src/any_vec_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ pub(crate) mod utils{
if Unknown::is::<AnyVecPtr::Element>(){
any_vec_raw.get_unchecked(index)
} else {
// AnyVecTyped::get_unchecked cause MIRI error
AnyVecTyped::<AnyVecPtr::Element, _>::new(NonNull::from(any_vec_raw))
.as_ptr().add(index)
as *const _ as *const u8
Expand All @@ -175,7 +174,6 @@ pub(crate) mod utils{
if Unknown::is::<AnyVecPtr::Element>(){
any_vec_raw.get_unchecked_mut(index)
} else {
// AnyVecTyped::get_unchecked_mut cause MIRI error
AnyVecTyped::<AnyVecPtr::Element, _>::new(NonNull::from(any_vec_raw))
.as_mut_ptr().add(index)
as *mut _ as *mut u8
Expand Down
32 changes: 32 additions & 0 deletions src/any_vec_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,38 @@ impl<M: MemBuilder> AnyVecRaw<M> {

self.len += 1;
}

/// # Safety
///
/// Type is not checked.
pub unsafe fn append_unchecked<T: 'static, OtherM: MemBuilder>(
&mut self, other: &mut AnyVecRaw<OtherM>
) {
self.reserve(other.len);

// copy
unsafe {
if !Unknown::is::<T>(){
ptr::copy_nonoverlapping(
other.mem.as_ptr().cast::<T>(),
self.mem.as_mut_ptr().cast::<T>().add(self.len),
other.len
);
} else {
let element_size = self.element_layout().size();
ptr::copy_nonoverlapping(
other.mem.as_ptr(),
self.mem.as_mut_ptr().add(self.len*element_size),
other.len*element_size
);
}
}

// update len(s)
self.len += other.len;
other.len = 0;

}

#[inline]
pub fn clear(&mut self){
Expand Down
25 changes: 25 additions & 0 deletions src/any_vec_typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ impl<'a, T: 'static, M: MemBuilder + 'a> AnyVecTyped<'a, T, M>{
}
}

/// Moves all the elements of `other` into `self`, leaving `other` empty.
///
/// # Panics
///
/// * Panics if out of memory.
pub fn append<OtherM: MemBuilder>(
&mut self, other: &mut AnyVecTyped<T, OtherM>
) {
unsafe{
self.this_mut().append_unchecked::<T, _>(other.this_mut());
}
}

#[inline]
pub fn drain(&mut self, range: impl RangeBounds<usize>)
-> impl ElementIterator<Item = T> + 'a
Expand Down Expand Up @@ -289,6 +302,18 @@ impl<'a, T: 'static + Debug, M: MemBuilder> Debug for AnyVecTyped<'a, T, M>{
}
}

impl<'a, T: 'static, M: MemBuilder> Extend<T> for AnyVecTyped<'a, T, M>{
fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
let iter = iter.into_iter();
self.this_mut().reserve(iter.size_hint().0);
// We can't prove that iterator will return actual len in size_hint(),
// so we have to push items as usual.
for v in iter {
self.push(v);
}
}
}

// Do not implement Index, since we can't do the same for AnyVec
/*
impl<'a, T: 'static, I: SliceIndex<[T]>> Index<I> for AnyVecTyped<'a, T> {
Expand Down
2 changes: 2 additions & 0 deletions tarpaulin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[default]
exclude-files = ["benches/*"]
Loading