From f2cde0750597c6de1cee4e6658164ae36b37dbf0 Mon Sep 17 00:00:00 2001 From: Avril Date: Wed, 10 Jun 2020 01:33:16 +0100 Subject: [PATCH] added README --- Cargo.toml | 2 +- README.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 26 ++++++++++++++++++----- 3 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 README.md diff --git a/Cargo.toml b/Cargo.toml index 00d59c0..80ee6fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "malloc-array" description = "libc heap array allocator" -version = "1.0.0" +version = "1.1.0" authors = ["Avril "] edition = "2018" license = "GPL-3.0-or-later" diff --git a/README.md b/README.md new file mode 100644 index 0000000..9d3f588 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# malloc-array - `Vec` like `malloc()` wrapper + +This crate provides a `vec!`-like macro, `heap!` for creating arrays managed with `malloc()` and `free()`. It also provides the container type `HeapArray` as a safe wrapper around these. + +See [documentation] for more details. + +[documentation]: https://docs.rs/malloc-array + +## Macro usage + +### Creating zero-initialised arrays. +These are created with `calloc()`. +``` rust +heap![Type, size]; +``` +Note that if `Type` does not support zero-initialisation it is undefined behaviour to drop or access any element of the returned array. To assign without dropping see the associated function [replace_and_forget]: + +``` rust +let mut array = heap![String; 3]; +array.replace_and_forget(0, format!("snibbedy")); +array.replace_and_forget(1, format!("snab")); +array.replace_and_forget(2, format!(":D")); + +drop(array); // This is now safe. +``` + + [replace_and_forget]: https://docs.rs/malloc-array/1.0.0/malloc_array/struct.HeapArray.html#method.replace_and_forget + +### Creating initialised arrays. +These are created with `malloc()` and set with `replace_and_forget` (or, for the special case of `u8` sized types, `memset`). +``` rust +heap![expression; size]; +``` + +### Creating n-element arrays. +These are created with `malloc()` and set with `replace_and_forget`. +``` rust +heap![expression_one, expression_two]; +``` + +### Creating empty arrays. +These are created with either `malloc(0)`, or if the `zst_noalloc` feature is enabled they do not allocate. +``` rust +heap![]; +``` +`zst_noalloc` is enabled by default and causes instances with `len_bytes() == 0` to have `NULL` internal pointers instead of dangling ones returned by `malloc(0)`. +This behaviour my not be desireable and if it is not, disable the default featues. + +### Dropping on free +Arrays created this way are dropped in a way that ensures each element is also dropped. For anything implementing the `Copy` trait, this is redundant. +To avoid this, pass the keyword `unsafe` to any of the above macro definitions: +``` rust +let bytes = heap![unsafe u8; 32]; //`u8` does not need to be dropped. +let references = heap![unsafe ":D"; 10]; //Neither does `&'static str`. +``` +Note that if the type does implement the `Drop` trait, then unless the elements are dropped manually (see [into_iter]) dropping the array can cause a resource leak. + + [into_iter]: https://docs.rs/malloc-array/1.0.0/malloc_array/struct.IntoIter.html + +# License +GPL'd with love <3 diff --git a/src/lib.rs b/src/lib.rs index d71b2a5..3a646bb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,9 @@ mod tests { #[test] fn non_trivial_type() { let heap = heap!["test one".to_owned(), "test two".to_owned()]; - + let refs = heap![unsafe "test three"; 2]; + + assert_eq!(&refs[..], &["test three", "test three"]); assert_eq!(heap.as_slice(), ["test one", "test two"]); } @@ -28,7 +30,7 @@ mod tests { #[test] fn reinterpret() { - let heap = heap![u8; 32]; + let heap = heap![0u8; 32]; unsafe { let heap = heap.reinterpret::(); assert_eq!(heap.len(), 8); @@ -184,9 +186,17 @@ macro_rules! heap { { let num = $number; let mut ha = $crate::HeapArray::new_uninit(num); - - for x in 0..num { - ha.replace_and_forget(x, $value); + + if ha.len() == ha.len_bytes() && ha.len() > 0 { + unsafe { + let mut vl = $value; + + ha.set_memory(*std::mem::transmute::<_, &mut u8>(&mut vl)); + } + } else { + for x in 0..num { + ha.replace_and_forget(x, $value); + } } ha @@ -244,6 +254,12 @@ impl HeapArray std::mem::size_of::() == 1 } + /// Set each byte to a value. + pub unsafe fn set_memory(&mut self, value: u8) + { + ptr::memset(self.ptr as *mut u8, value, self.len_bytes()); + } + /// Creates a new `HeapArray` from zeroed memory. pub fn new(size: usize) -> Self {