#![cfg(all(feature = "alloc", feature = "zeroize"))] #![cfg_attr(feature = "nightly", feature(allocator_api))] use core::alloc::Layout; use core::cell::RefCell; use core::ptr::NonNull; use core::slice; use flex_alloc::{ alloc::{Allocator, Global, SpillAlloc, ZeroizingAlloc}, storage::{array_storage, byte_storage}, vec, vec::{Vec as FlexVec, ZeroizingVec}, }; #[derive(Debug)] struct TestAlloc { alloc: A, released: RefCell>>, } impl TestAlloc { fn new(alloc: A) -> Self { Self { alloc, released: RefCell::new(Vec::new()), } } } unsafe impl Allocator for &TestAlloc { fn allocate(&self, layout: Layout) -> Result, flex_alloc::alloc::AllocError> { self.alloc.allocate(layout) } fn allocate_zeroed( &self, layout: Layout, ) -> Result, flex_alloc::alloc::AllocError> { self.alloc.allocate_zeroed(layout) } unsafe fn grow( &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, ) -> Result, flex_alloc::alloc::AllocError> { self.alloc.grow(ptr, old_layout, new_layout) } unsafe fn grow_zeroed( &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, ) -> Result, flex_alloc::alloc::AllocError> { self.alloc.grow_zeroed(ptr, old_layout, new_layout) } unsafe fn shrink( &self, ptr: NonNull, old_layout: Layout, new_layout: Layout, ) -> Result, flex_alloc::alloc::AllocError> { self.alloc.shrink(ptr, old_layout, new_layout) } unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { let cp = Vec::from(unsafe { slice::from_raw_parts(ptr.as_ptr(), layout.size()) }); self.released.borrow_mut().push(cp); self.alloc.deallocate(ptr, layout) } } #[test] fn test_alloc_log() { // check functioning of alloc log let alloc = TestAlloc::new(Global); let b = vec![in &alloc; 99usize]; drop(b); let log = alloc.released.borrow().clone(); assert_eq!(log.len(), 1); assert!(log[0].starts_with(&99u32.to_ne_bytes())); } #[test] fn vec_zeroizing_alloc_global() { let mut v = FlexVec::::new_in(ZeroizingAlloc::::default()); v.extend([1, 2, 3]); } #[test] fn vec_zeroizing_alloc_global_verify() { let alloc = TestAlloc::new(Global); let mut v = FlexVec::::new_in(ZeroizingAlloc(&alloc)); v.push(1usize); drop(v); let log = alloc.released.borrow().clone(); assert_eq!(log.len(), 1); assert!(log[0].iter().all(|i| *i == 0)); } #[test] fn vec_zeroizing_array_storage() { let mut z = zeroize::Zeroizing::new(array_storage::()); let mut v = FlexVec::::new_in(&mut *z); v.push(1); } #[test] fn vec_zeroizing_byte_storage() { let mut z = zeroize::Zeroizing::new(byte_storage::<100>()); let mut v = FlexVec::::new_in(&mut *z); v.push(1); } #[test] fn vec_zeroizing_array_storage_spill() { let mut z = zeroize::Zeroizing::new(array_storage::()); let mut v = FlexVec::::new_in(z.spill_alloc()); v.extend([1, 2, 3]); } #[test] fn vec_zeroizing_array_storage_spill_verify() { let alloc = TestAlloc::new(Global); let mut z = zeroize::Zeroizing::new(array_storage::()); let mut v = FlexVec::::new_in(z.spill_alloc_in(&alloc)); v.extend([1, 2, 3]); drop(v); let log = alloc.released.borrow().clone(); assert_eq!(log.len(), 1); assert!(log[0].iter().all(|i| *i == 0)); } #[test] fn vec_zeroizing_byte_storage_spill() { let mut z = zeroize::Zeroizing::new(byte_storage::<10>()); let mut v = FlexVec::::new_in(z.spill_alloc()); v.extend([1, 2, 3]); } #[test] fn vec_zeroizing_byte_storage_spill_verify() { let alloc = TestAlloc::new(Global); let mut z = zeroize::Zeroizing::new(byte_storage::<10>()); let mut v = FlexVec::::new_in(z.spill_alloc_in(&alloc)); v.extend([1, 2, 3]); drop(v); let log = alloc.released.borrow().clone(); assert_eq!(log.len(), 1); assert!(log[0].iter().all(|i| *i == 0)); } #[test] fn vec_zeroizingvec_alias() { let mut v = ZeroizingVec::new(); v.extend([1, 2, 3]); }