use std::alloc::System;
use stats_alloc::{StatsAlloc, INSTRUMENTED_SYSTEM};
use abin::{AnyBin, BinFactory, IntoSync, IntoUnSync, IntoUnSyncView, NewBin, NewSBin};
use utils::*;
#[global_allocator]
static GLOBAL: &StatsAlloc<System> = &INSTRUMENTED_SYSTEM;
pub mod utils;
const STACK_BIN_LEN: usize = 3 * core::mem::size_of::<usize>() - 1;
#[test]
fn no_alloc_guarantees() {
mem_scoped(&GLOBAL, &MaNoLeak, || {
empty();
small_binaries_are_stack_allocated();
vec_can_be_extracted_without_allocation();
convert_into_sync_un_sync();
no_alloc_clone();
slice_does_not_allocate();
into_vec_does_not_allocate();
});
}
fn empty() {
mem_scoped(&GLOBAL, &MaNoAllocNoDealloc, || {
NewBin::empty();
NewSBin::empty();
});
}
fn small_binaries_are_stack_allocated() {
let empty_slice: &[u8] = &[];
let empty_vec_1 = Vec::from(empty_slice);
let empty_vec_2 = Vec::from(empty_slice);
let max_stack_alloc_vec_1 = generate_small_vec_that_fits_on_stack();
let max_stack_alloc_vec_2 = generate_small_vec_that_fits_on_stack();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
NewBin::from_given_vec(empty_vec_1);
NewBin::copy_from_slice(empty_slice);
NewSBin::from_given_vec(empty_vec_2);
NewSBin::copy_from_slice(empty_slice);
NewBin::copy_from_slice(max_stack_alloc_vec_1.as_slice());
NewBin::from_given_vec(max_stack_alloc_vec_1);
NewSBin::copy_from_slice(max_stack_alloc_vec_2.as_slice());
NewSBin::from_given_vec(max_stack_alloc_vec_2);
});
}
fn vec_can_be_extracted_without_allocation() {
let bin_gen = BinGen::new(0, 800);
let vec = bin_gen.generate_to_vec();
let vec_clone = vec.clone();
let bin_1 = NewBin::from_given_vec(vec);
let vec_from_bin = bin_1.into_vec();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
let bin_2 = NewBin::from_given_vec(vec_from_bin);
let vec_from_bin_2 = bin_2.into_vec();
assert_eq!(vec_clone, vec_from_bin_2);
});
}
fn convert_into_sync_un_sync() {
let bin_gen = BinGen::new(0, 200);
let vec = bin_gen.generate_to_vec();
let bin_1 = NewBin::empty();
let bin_2 = NewBin::from_static("Hello, slice!".as_bytes());
let bin_3 = NewBin::copy_from_slice(vec.as_slice());
let bin_4 = NewSBin::copy_from_slice(vec.as_slice()).un_sync();
let bin_5 = NewBin::from_given_vec(generate_small_vec_that_fits_on_stack());
let bin_6 = NewSBin::from_given_vec(generate_small_vec_that_fits_on_stack()).un_sync();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
let sync_bin1 = bin_1.into_sync();
let sync_bin2 = bin_2.into_sync();
let sync_bin3 = bin_3.into_sync();
let sync_bin4 = bin_4.into_sync();
let sync_bin5 = bin_5.into_sync();
let sync_bin6 = bin_6.into_sync();
sync_bin1.un_sync_convert();
sync_bin2.un_sync_convert();
sync_bin3.un_sync_convert();
sync_bin4.un_sync_convert();
sync_bin5.un_sync_convert();
sync_bin6.un_sync_convert();
});
}
fn no_alloc_clone() {
let bin_gen = BinGen::new(0, STACK_BIN_LEN * 4);
let vec = bin_gen.generate_to_vec();
let bin_1 = NewBin::empty();
let bin_2 = NewBin::from_static("Hello, slice!".as_bytes());
let bin_3 = NewBin::from_given_vec(vec.clone());
let bin_4 = NewSBin::from_given_vec(vec.clone()).un_sync();
let bin_5 = NewBin::from_given_vec(generate_small_vec_that_fits_on_stack());
let bin_6 = NewSBin::from_given_vec(generate_small_vec_that_fits_on_stack()).un_sync();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
let _ignored = bin_1.clone();
let _ignored = bin_2.clone();
let _ignored = bin_3.clone();
let _ignored = bin_4.clone();
let _ignored = bin_5.clone();
let _ignored = bin_6.clone();
});
}
fn slice_does_not_allocate() {
let len = 200;
let bin_gen = BinGen::new(0, len);
let vec = bin_gen.generate_to_vec();
let bin_1 = NewBin::empty();
let bin_2 = NewBin::from_static("Hello, slice!".as_bytes());
let bin_3 = NewBin::from_given_vec(vec.clone());
let bin_4 = NewSBin::from_given_vec(vec.clone()).un_sync();
let bin_5 = NewBin::from_given_vec(generate_small_vec_that_fits_on_stack());
let bin_6 = NewSBin::from_given_vec(generate_small_vec_that_fits_on_stack()).un_sync();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
assert_eq!(&[] as &[u8], bin_1.slice(0..0).unwrap().as_slice());
assert_eq!("ello".as_bytes(), bin_2.slice(1..5).unwrap().as_slice());
assert!(bin_3.slice(10..len - 5).is_some());
assert!(bin_4.slice(10..len - 5).is_some());
assert!(bin_5.slice(1..STACK_BIN_LEN - 1).is_some());
assert!(bin_6.slice(1..STACK_BIN_LEN - 1).is_some());
});
}
fn into_vec_does_not_allocate() {
let len = STACK_BIN_LEN * 2;
let bin_gen = BinGen::new(0, len);
let vec = bin_gen.generate_to_vec();
let bin_1 = NewBin::empty();
let bin_2_allocates = NewBin::from_static("Hello, slice!".as_bytes());
let bin_3 = NewBin::copy_from_slice(vec.as_slice());
let bin_4 = NewSBin::copy_from_slice(vec.as_slice()).un_sync();
let bin_5_allocates = NewBin::from_given_vec(generate_small_vec_that_fits_on_stack());
let bin_6_allocates =
NewSBin::from_given_vec(generate_small_vec_that_fits_on_stack()).un_sync();
mem_scoped(&GLOBAL, &MaNoAllocNoReAlloc, || {
assert_eq!(bin_1.into_vec(), Vec::new());
bin_3.into_vec();
bin_4.into_vec();
});
mem_scoped(&GLOBAL, &MaDoesAllocate, || {
bin_2_allocates.into_vec();
});
mem_scoped(&GLOBAL, &MaDoesAllocate, || {
bin_5_allocates.into_vec();
});
mem_scoped(&GLOBAL, &MaDoesAllocate, || {
bin_6_allocates.into_vec();
});
}
fn generate_small_vec_that_fits_on_stack() -> Vec<u8> {
let bin_gen = BinGen::new(0, STACK_BIN_LEN);
bin_gen.generate_to_vec()
}