hivex 0.2.1

(Hopefully) idiomatic bindings to the Hivex library
//! LibC allocator compatibility proxy

use {
	allocator_api2::alloc::{AllocError, Allocator},
	std::{
		alloc::{GlobalAlloc, Layout},
		ptr::NonNull,
	},
};

/// Box which uses allocator from LibC, used by Hivex to ensure
/// correct deallocations.
pub type LibCBox<T> = allocator_api2::boxed::Box<T, LibCAlloc>;

/// Proxy for [`libc_alloc::LibcAlloc`] to use with [`allocator_api2`]
#[derive(Clone, Default)]
#[repr(transparent)]
pub struct LibCAlloc;

unsafe impl Allocator for LibCAlloc {
	fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
		let size = layout.size();
		let ptr = unsafe { libc_alloc::LibcAlloc.alloc(layout) };
		if ptr.is_null() {
			return Err(AllocError);
		}

		let slice = unsafe { std::slice::from_raw_parts_mut(ptr, size) };

		unsafe { Ok(NonNull::new_unchecked(&mut *slice)) }
	}

	unsafe fn deallocate(&self, ptr: std::ptr::NonNull<u8>, layout: std::alloc::Layout) {
		unsafe { libc_alloc::LibcAlloc.dealloc(ptr.as_ptr(), layout) }
	}
}