malloc_buf-1.0.0/Cargo.toml01006440405350655273700000001557130525006220014021 0ustar0000000000000000# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "malloc_buf" version = "1.0.0" authors = ["Steven Sheldon"] exclude = [".gitignore"] description = "Structs for handling malloc'd memory passed to Rust." documentation = "http://ssheldon.github.io/malloc_buf/malloc_buf/" license = "MIT" repository = "https://github.com/SSheldon/malloc_buf" [dependencies.libc] version = ">= 0.1, < 0.3" malloc_buf-1.0.0/Cargo.toml.orig01006440405350655273700000000535130525006220014753 0ustar0000000000000000[package] name = "malloc_buf" version = "1.0.0" authors = ["Steven Sheldon"] description = "Structs for handling malloc'd memory passed to Rust." repository = "https://github.com/SSheldon/malloc_buf" documentation = "http://ssheldon.github.io/malloc_buf/malloc_buf/" license = "MIT" exclude = [".gitignore"] [dependencies] libc = ">= 0.1, < 0.3" malloc_buf-1.0.0/src/lib.rs01006440405350655273700000010576130524777430014016 0ustar0000000000000000#![no_std] extern crate libc; #[cfg(test)] extern crate std; use core::fmt; use core::ops::Deref; use core::ptr; use core::slice; use core::str::{Utf8Error, self}; use libc::{c_char, c_void}; const DUMMY_PTR: *mut c_void = 0x1 as *mut c_void; /// A type that represents a `malloc`'d chunk of memory. /// When dropped, a `Malloc` will `free` that memory. pub struct Malloc { ptr: *mut T, } impl Malloc { /** Constructs a new `Malloc` for a `malloc`'d value. Unsafe because there must be a valid instance of `T` at `ptr`. */ pub unsafe fn from_ptr(ptr: *mut T) -> Malloc { Malloc { ptr: ptr } } } impl Malloc<[T]> { /** Constructs a new `Malloc` for a `malloc`'d buffer with the given length at the given pointer. Unsafe because there must be `len` contiguous, valid instances of `T` at `ptr`. The given pointer must not be null unless the length is 0; this function will specially handle null, 0-length buffers safely. */ pub unsafe fn from_array(ptr: *mut T, len: usize) -> Malloc<[T]> { // Even a 0-size slice cannot be null, so just use another pointer let ptr = if ptr.is_null() && len == 0 { DUMMY_PTR as *mut T } else { ptr }; let slice = slice::from_raw_parts(ptr, len); Malloc { ptr: slice as *const [T] as *mut [T] } } } impl Malloc { /** Constructs a new `Malloc` for a `malloc`'d nul-terminated C string at the given pointer. Returns an error if the bytes are not valid UTF8. Unsafe because `ptr` must point to valid, nul-terminated bytes. Once created, when dereferenced the `Malloc` will return the string without its nul-terminator. */ pub unsafe fn from_c_str(ptr: *mut c_char) -> Result, Utf8Error> { let len = libc::strlen(ptr); let slice = slice::from_raw_parts(ptr as *mut u8, len); str::from_utf8(slice).map(|s| { Malloc { ptr: s as *const str as *mut str } }) } } impl Deref for Malloc { type Target = T; fn deref(&self) -> &T { unsafe { &*self.ptr } } } impl Drop for Malloc { fn drop(&mut self) { if (self.ptr as *mut c_void) != DUMMY_PTR { unsafe { ptr::drop_in_place(self.ptr); libc::free(self.ptr as *mut c_void); } } } } impl fmt::Debug for Malloc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Display for Malloc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&**self, f) } } impl AsRef for Malloc { fn as_ref(&self) -> &T { &**self } } #[cfg(test)] mod tests { use std::mem; use std::ptr; use libc::{c_char, self}; use super::Malloc; fn alloc(value: T) -> *mut T { unsafe { let ptr = libc::malloc(mem::size_of::()) as *mut T; ptr::write(ptr, value); ptr } } #[test] fn test_null_buf() { let buf = unsafe { Malloc::<[u32]>::from_array(ptr::null_mut(), 0) }; assert!(&*buf == []); assert!(Some(&*buf) == Some(&[])); } #[test] fn test_buf() { let ptr = alloc([1, 2, 3]); let buf = unsafe { Malloc::from_array(ptr as *mut i32, 3) }; assert!(&*buf == [1, 2, 3]); } #[test] fn test_string() { let ptr = alloc(['h' as c_char, 'e' as c_char, 'y' as c_char, '\0' as c_char]); let s = unsafe { Malloc::from_c_str(ptr as *mut c_char).unwrap() }; assert!(&*s == "hey"); } #[test] fn test_single() { use std::string::ToString; let m = unsafe { Malloc::from_ptr(alloc(4)) }; assert!(&*m == &4); let m = unsafe { Malloc::from_ptr(alloc("hello".to_string())) }; assert!(&**m == "hello"); } #[test] fn test_drop() { use std::rc::Rc; let num: Rc = Rc::new(4); assert_eq!(Rc::strong_count(&num), 1); let ptr = alloc([num.clone(), num.clone()]); let buf = unsafe { Malloc::from_array(ptr as *mut Rc, 2) }; assert_eq!(Rc::strong_count(&num), 3); drop(buf); assert_eq!(Rc::strong_count(&num), 1); } }