diff --git a/iceoryx2-bb/container/src/vec.rs b/iceoryx2-bb/container/src/vec.rs index 132f21518..5b2bfa21c 100644 --- a/iceoryx2-bb/container/src/vec.rs +++ b/iceoryx2-bb/container/src/vec.rs @@ -64,6 +64,8 @@ use std::{ alloc::Layout, mem::MaybeUninit, + ops::Deref, + ops::DerefMut, sync::atomic::{AtomicBool, Ordering}, }; @@ -136,6 +138,42 @@ impl RelocatableContainer for Vec { } } +impl Deref for Vec { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::())); + unsafe { core::slice::from_raw_parts((*self.data_ptr.as_ptr()).as_ptr(), self.len) } + } +} + +impl DerefMut for Vec { + fn deref_mut(&mut self) -> &mut Self::Target { + self.verify_init(&format!("Vec<{}>::push()", std::any::type_name::())); + unsafe { + core::slice::from_raw_parts_mut((*self.data_ptr.as_mut_ptr()).as_mut_ptr(), self.len) + } + } +} + +impl PartialEq for Vec { + 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 Eq for Vec {} + impl Vec { fn verify_init(&self, source: &str) { if !self @@ -212,6 +250,27 @@ impl Vec { 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`]. /// @@ -249,62 +308,6 @@ impl Vec { 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::())); - 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::())); - 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 @@ -330,6 +333,36 @@ impl Default for FixedSizeVec { } } +impl Deref for FixedSizeVec { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + self.state.deref() + } +} + +impl DerefMut for FixedSizeVec { + fn deref_mut(&mut self) -> &mut Self::Target { + self.state.deref_mut() + } +} + +impl PartialEq for FixedSizeVec { + fn eq(&self, other: &Self) -> bool { + self.state.eq(&other.state) + } +} + +impl Eq for FixedSizeVec {} + +impl Clone for FixedSizeVec { + fn clone(&self) -> Self { + let mut new_self = Self::new(); + new_self.extend_from_slice(self.deref()); + new_self + } +} + unsafe impl Send for FixedSizeVec {} unsafe impl Sync for FixedSizeVec {} @@ -373,6 +406,14 @@ impl FixedSizeVec { 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 { @@ -383,38 +424,4 @@ impl FixedSizeVec { 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) } - } } diff --git a/iceoryx2-bb/container/tests/vec_tests.rs b/iceoryx2-bb/container/tests/vec_tests.rs index d2c3d2d4a..72b09a159 100644 --- a/iceoryx2-bb/container/tests/vec_tests.rs +++ b/iceoryx2-bb/container/tests/vec_tests.rs @@ -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); } @@ -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); +}