From a286993262a146a13925299e357840f0b23b70b4 Mon Sep 17 00:00:00 2001 From: Adam Cimarosti Date: Tue, 8 Oct 2024 09:46:36 +0100 Subject: [PATCH 1/2] removed Clone trait and introduced TryClone trait --- Cargo.toml | 2 +- src/lib.rs | 1 + src/try_clone.rs | 10 ++++++++++ src/vec.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/try_clone.rs diff --git a/Cargo.toml b/Cargo.toml index a620835..45d0038 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "alloc-checked" description = "Collections that don't panic on alloc failures" authors = ["Adam Cimarosti "] -version = "0.1.0" +version = "0.1.1" edition = "2021" repository = "https://github.com/questdb/alloc-checked" keywords = ["alloc", "collections", "no-std", "safe-allocation", "container"] diff --git a/src/lib.rs b/src/lib.rs index c28096c..c144bdf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,4 +5,5 @@ extern crate alloc; extern crate core; +pub mod try_clone; pub mod vec; diff --git a/src/try_clone.rs b/src/try_clone.rs new file mode 100644 index 0000000..62387f1 --- /dev/null +++ b/src/try_clone.rs @@ -0,0 +1,10 @@ +/// A variant of the `Clone` trait which can fail. +pub trait TryClone: Sized { + type Error; + + fn try_clone(&self) -> Result; + fn try_clone_from(&mut self, source: &Self) -> Result<(), Self::Error> { + *self = source.try_clone()?; + Ok(()) + } +} diff --git a/src/vec.rs b/src/vec.rs index d0f988e..fcdacfa 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,3 +1,4 @@ +use crate::try_clone::TryClone; use alloc::alloc::Allocator; use alloc::collections::TryReserveError; use alloc::vec::Vec as InnerVec; @@ -5,7 +6,6 @@ use core::fmt::Debug; use core::ops::{Deref, DerefMut, Index, IndexMut}; use core::slice::SliceIndex; -#[derive(Clone)] pub struct Vec { inner: InnerVec, } @@ -186,6 +186,16 @@ impl Vec { } } +impl TryClone for Vec { + type Error = TryReserveError; + + fn try_clone(&self) -> Result { + let mut cloned = Self::with_capacity_in(self.len(), self.allocator().clone())?; + cloned.extend_from_slice(self.inner.as_slice())?; + Ok(cloned) + } +} + impl, A: Allocator> Index for Vec { type Output = I::Output; @@ -316,7 +326,7 @@ mod tests { return Err(AllocError); } let allocated = Global.allocate(layout)?; - let true_new_in_use = self.in_use.fetch_add(layout.size(), Ordering::SeqCst); + let true_new_in_use = self.in_use.fetch_add(allocated.len(), Ordering::SeqCst); unsafe { if true_new_in_use > self.watermark { let ptr = allocated.as_ptr() as *mut u8; @@ -788,7 +798,7 @@ mod tests { let wma = WatermarkAllocator::new(128); let mut vec1 = Vec::new_in(wma); vec1.extend(vec![1, 2, 3]).unwrap(); - let vec2 = vec1.clone(); + let vec2 = vec1.try_clone().unwrap(); assert_eq!(vec1, vec2); let e0vec1 = get_first_elem_vec(vec1); @@ -814,7 +824,8 @@ mod tests { let wma = WatermarkAllocator::new(128); let mut vec1 = Vec::new_in(wma); vec1.extend(vec![1, 2, 3]).unwrap(); - let vec2 = vec1.clone(); + let vec2 = vec1.try_clone().unwrap(); + assert_eq!(vec1, vec2); let d0vec1 = doubled_first_elem_vec(vec1); let d0vec2 = doubled_first_elem_slice(vec2); @@ -822,4 +833,15 @@ mod tests { assert_eq!(d0vec1, 2); assert_eq!(d0vec2, 2); } + + #[test] + fn test_try_clone() { + let wma = WatermarkAllocator::new(64); + let mut vec1 = Vec::new_in(wma.clone()); + vec1.extend([1usize, 2, 3, 4, 5, 6, 7, 8]).unwrap(); + assert_eq!(vec1.len(), 8); + assert_eq!(vec1.capacity(), 8); + assert_eq!(wma.in_use(), 64); + assert!(vec1.try_clone().is_err()); + } } From 1bac60d39a4ac93d4dfa17b43e3bc7c02e4b799a Mon Sep 17 00:00:00 2001 From: Adam Cimarosti Date: Tue, 8 Oct 2024 12:22:59 +0100 Subject: [PATCH 2/2] restricting TryClone to T: Copy as T: Clone is fallible --- src/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vec.rs b/src/vec.rs index fcdacfa..3053e90 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -186,7 +186,7 @@ impl Vec { } } -impl TryClone for Vec { +impl TryClone for Vec { type Error = TryReserveError; fn try_clone(&self) -> Result {