heapbuf 0.1.3

Fixed size heap buffer with optional custom alignment, ref counting and custom destructor logic.
Documentation
use heapbuf::DynDestructor;
use std::ptr::null_mut;
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
use std::sync::Arc;

static PTR: AtomicPtr<u8> = AtomicPtr::new(null_mut());

static SZ: AtomicUsize = AtomicUsize::new(0);

fn test_it(ptr: *mut u8, sz: usize) {
    PTR.store(ptr, Ordering::SeqCst);
    assert_eq!(ptr, PTR.load(Ordering::SeqCst));
    SZ.store(sz, Ordering::SeqCst);
    assert_eq!(sz, SZ.load(Ordering::SeqCst));
}
#[test]
fn test_destructor_called() {
    PTR.store(null_mut(), Ordering::SeqCst);
    SZ.store(0, Ordering::SeqCst);

    let mut x = vec![0u8; 16];
    let ptr = x.as_mut_ptr();
    test_it(null_mut(), 2);


    let hb = unsafe { heapbuf::HBuf::from_raw_parts_with_destructor(ptr, 16, test_it) };
    let hb = std::hint::black_box(hb);
    drop(hb);
    assert_eq!(ptr, PTR.load(Ordering::SeqCst));
    assert_eq!(16, SZ.load(Ordering::SeqCst));
}


#[derive(Debug, Default, Clone)]
struct DynDes1(Arc<AtomicUsize>);

#[derive(Debug, Default, Clone)]
struct DynDes2(Arc<AtomicUsize>);

impl DynDestructor for DynDes1 {
    fn destroy(&mut self, ptr: *mut u8, size: usize) {
        self.0.fetch_add(1, Ordering::SeqCst);
        PTR.store(ptr, Ordering::SeqCst);
        SZ.store(size, Ordering::SeqCst);
    }
}

impl DynDestructor for DynDes2 {
    fn destroy(&mut self, ptr: *mut u8, size: usize) {
        self.0.fetch_add(2, Ordering::SeqCst);
        PTR.store(ptr, Ordering::SeqCst);
        SZ.store(size, Ordering::SeqCst);
    }
}
#[test]
fn test_dyn_destructor_called() {
    let mut x = vec![0u8; 16];
    let ptr = x.as_mut_ptr();
    let des1 = DynDes1::default();

    PTR.store(null_mut(), Ordering::SeqCst);
    SZ.store(0, Ordering::SeqCst);


    let hb = unsafe { heapbuf::HBuf::from_raw_parts_with_dyn_destructor(ptr, 16, Box::new(des1.clone())) };
    let hb = std::hint::black_box(hb);
    drop(hb);

    assert_eq!(ptr, PTR.load(Ordering::SeqCst));
    assert_eq!(16, SZ.load(Ordering::SeqCst));

    PTR.store(null_mut(), Ordering::SeqCst);
    SZ.store(0, Ordering::SeqCst);

    let des2 = DynDes2::default();
    let hb = unsafe { heapbuf::HBuf::from_raw_parts_with_dyn_destructor(ptr, 16, Box::new(des2.clone())) };
    let hb = std::hint::black_box(hb);
    drop(hb);

    assert_eq!(ptr, PTR.load(Ordering::SeqCst));
    assert_eq!(16, SZ.load(Ordering::SeqCst));

    PTR.store(null_mut(), Ordering::SeqCst);
    SZ.store(0, Ordering::SeqCst);

    assert_eq!(des1.0.load(Ordering::SeqCst), 1);
    assert_eq!(des2.0.load(Ordering::SeqCst), 2);
}