Skip to content

Commit

Permalink
[#58] Add Deref, DerefMut, Clone, Eq, PartialEq, extend_from_slice to…
Browse files Browse the repository at this point in the history
… (FixedSize)Vec
  • Loading branch information
elfenpiff committed Dec 25, 2023
1 parent dc84df5 commit 2b4ed86
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 92 deletions.
187 changes: 97 additions & 90 deletions iceoryx2-bb/container/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
use std::{
alloc::Layout,
mem::MaybeUninit,
ops::Deref,
ops::DerefMut,
sync::atomic::{AtomicBool, Ordering},
};

Expand Down Expand Up @@ -136,6 +138,42 @@ impl<T> RelocatableContainer for Vec<T> {
}
}

impl<T> Deref for Vec<T> {
type Target = [T];

fn deref(&self) -> &Self::Target {
self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::<T>()));
unsafe { core::slice::from_raw_parts((*self.data_ptr.as_ptr()).as_ptr(), self.len) }
}
}

impl<T> DerefMut for Vec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::<T>()));
unsafe {
core::slice::from_raw_parts_mut((*self.data_ptr.as_mut_ptr()).as_mut_ptr(), self.len)
}
}
}

impl<T: PartialEq> PartialEq for Vec<T> {
fn eq(&self, other: &Self) -> bool {
if other.len() != self.len() {
return false;
}

for i in 0..self.len() {
if other[i] != self[i] {
return false;
}
}

true
}
}

impl<T: Eq> Eq for Vec<T> {}

impl<T> Vec<T> {
fn verify_init(&self, source: &str) {
if !self
Expand Down Expand Up @@ -212,6 +250,27 @@ impl<T> Vec<T> {
self.len += 1;
}

/// Append all elements from other via [`Clone`].
///
/// # Safety
///
/// * Only use this method when [`Vec::init()`] was called before
///
pub unsafe fn extend_from_slice(&mut self, other: &[T]) -> bool
where
T: Clone,
{
if self.capacity < self.len + other.len() {
return false;
}

for element in other {
self.push_unchecked(element.clone());
}

true
}

/// Removes the last element of the vector and returns it to the user. If the vector is empty
/// it returns [`None`].
///
Expand Down Expand Up @@ -249,62 +308,6 @@ impl<T> Vec<T> {

value.assume_init()
}

/// Returns a reference to the element at the specified index. If the index is out of bounds it
/// returns [`None`].
///
/// # Safety
///
/// * Only use this method when [`Vec::init()`] was called before
///
pub unsafe fn get(&self, index: usize) -> Option<&T> {
if self.len <= index {
None
} else {
self.verify_init(&format!("Vec<{}>::get()", std::any::type_name::<T>()));
Some(self.get_unchecked(index))
}
}

/// Returns a reference to the element at the specified index. The user has to ensure that the
/// index is present in the vector otherwise it leads to undefined behavior.
///
/// # Safety
///
/// * Only use this method when [`Vec::init()`] was called before
/// * The index must be not out of bounds
///
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
&*(*self.data_ptr.as_ptr().add(index)).as_ptr()
}

/// Returns a mutable reference to the element at the specified index. If the index is out of
/// bounds it returns [`None`].
///
/// # Safety
///
/// * Only use this method when [`Vec::init()`] was called before
///
pub unsafe fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if self.len <= index {
None
} else {
self.verify_init(&format!("Vec<{}>::get_mut()", std::any::type_name::<T>()));
Some(self.get_unchecked_mut(index))
}
}

/// Returns a mutable reference to the element at the specified index. The user has to ensure
/// that the index is present in the vector otherwise it leads to undefined behavior.
///
/// # Safety
///
/// * Only use this method when [`Vec::init()`] was called before
/// * The index must be not out of bounds
///
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
&mut *(*self.data_ptr.as_mut_ptr().add(index)).as_mut_ptr()
}
}

/// Relocatable vector with compile time fixed size capacity. In contrast to its counterpart the
Expand All @@ -330,6 +333,36 @@ impl<T, const CAPACITY: usize> Default for FixedSizeVec<T, CAPACITY> {
}
}

impl<T, const CAPACITY: usize> Deref for FixedSizeVec<T, CAPACITY> {
type Target = [T];

fn deref(&self) -> &Self::Target {
self.state.deref()
}
}

impl<T, const CAPACITY: usize> DerefMut for FixedSizeVec<T, CAPACITY> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.state.deref_mut()
}
}

impl<T: PartialEq, const CAPACITY: usize> PartialEq for FixedSizeVec<T, CAPACITY> {
fn eq(&self, other: &Self) -> bool {
self.state.eq(&other.state)
}
}

impl<T: Eq, const CAPACITY: usize> Eq for FixedSizeVec<T, CAPACITY> {}

impl<T: Clone, const CAPACITY: usize> Clone for FixedSizeVec<T, CAPACITY> {
fn clone(&self) -> Self {
let mut new_self = Self::new();
new_self.extend_from_slice(self.deref());
new_self
}
}

unsafe impl<T: Send, const CAPACITY: usize> Send for FixedSizeVec<T, CAPACITY> {}
unsafe impl<T: Sync, const CAPACITY: usize> Sync for FixedSizeVec<T, CAPACITY> {}

Expand Down Expand Up @@ -373,6 +406,14 @@ impl<T, const CAPACITY: usize> FixedSizeVec<T, CAPACITY> {
unsafe { self.state.fill(value) }
}

/// Append all elements from other via [`Clone`].
pub fn extend_from_slice(&mut self, other: &[T]) -> bool
where
T: Clone,
{
unsafe { self.state.extend_from_slice(other) }
}

/// Removes the last element of the vector and returns it to the user. If the vector is empty
/// it returns [`None`].
pub fn pop(&mut self) -> Option<T> {
Expand All @@ -383,38 +424,4 @@ impl<T, const CAPACITY: usize> FixedSizeVec<T, CAPACITY> {
pub fn clear(&mut self) {
unsafe { self.state.clear() }
}

/// Returns a reference to the element at the specified index. If the index is out of bounds it
/// returns [`None`].
pub fn get(&self, index: usize) -> Option<&T> {
unsafe { self.state.get(index) }
}

/// Returns a reference to the element at the specified index. The user has to ensure that the
/// index is present in the vector otherwise it leads to undefined behavior.
///
/// # Safety
///
/// * The index must be not out of bounds
///
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
unsafe { self.state.get_unchecked(index) }
}

/// Returns a mutable reference to the element at the specified index. If the index is out of
/// bounds it returns [`None`].
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
unsafe { self.state.get_mut(index) }
}

/// Returns a mutable reference to the element at the specified index. The user has to ensure
/// that the index is present in the vector otherwise it leads to undefined behavior.
///
/// # Safety
///
/// * The index must be not out of bounds
///
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
unsafe { self.state.get_unchecked_mut(index) }
}
}
50 changes: 48 additions & 2 deletions iceoryx2-bb/container/tests/vec_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ fn vec_push_pop_works_with_uninitialized_memory() {
assert_that!(sut.is_full(), eq true);

for i in 0..sut.capacity() {
assert_that!(unsafe { *sut.get(i).unwrap() }, eq i * 2 + 3);
assert_that!(unsafe { *sut.get_mut(i).unwrap() }, eq i * 2 + 3);
assert_that!(*sut.get(i).unwrap(), eq i * 2 + 3);
assert_that!(*sut.get_mut(i).unwrap(), eq i * 2 + 3);
assert_that!(unsafe { *sut.get_unchecked(i) }, eq i * 2 + 3);
assert_that!(unsafe { *sut.get_unchecked_mut(i) }, eq i * 2 + 3);
}
Expand Down Expand Up @@ -151,3 +151,49 @@ fn fixed_size_vec_valid_after_move() {
assert_that!(result, eq Some((sut2.capacity() - i - 1) * 2 + 3));
}
}

#[test]
fn fixed_size_vec_eq_works() {
let create_vec = |n| {
let mut sut = Sut::new();
for i in 0..n {
sut.push(4 * i + 3);
}
sut
};

let vec1 = create_vec(SUT_CAPACITY - 2);
let vec2 = create_vec(SUT_CAPACITY - 1);
let vec3 = create_vec(SUT_CAPACITY);

assert_that!(Sut::new() == Sut::new(), eq true);

assert_that!(vec1 == vec1, eq true);
assert_that!(vec1 == vec2, eq false);
assert_that!(vec1 == vec3, eq false);
assert_that!(vec1 == Sut::new(), eq false);

assert_that!(vec2 == vec1, eq false);
assert_that!(vec2 == vec2, eq true);
assert_that!(vec2 == vec3, eq false);
assert_that!(vec2 == Sut::new(), eq false);

assert_that!(vec3 == vec1, eq false);
assert_that!(vec3 == vec2, eq false);
assert_that!(vec3 == vec3, eq true);
assert_that!(vec3 == Sut::new(), eq false);
}

#[test]
fn fixed_size_vec_clone_works() {
let mut sut = Sut::new();
let sut1 = sut.clone();
for i in 0..SUT_CAPACITY {
sut.push(8 * i + 6);
}

let sut2 = sut.clone();

assert_that!(Sut::new() == sut1, eq true);
assert_that!(sut == sut2, eq true);
}

0 comments on commit 2b4ed86

Please sign in to comment.