summaryrefslogtreecommitdiffstats
path: root/third_party/rust/memalloc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/memalloc')
-rw-r--r--third_party/rust/memalloc/.cargo-checksum.json1
-rw-r--r--third_party/rust/memalloc/Cargo.toml10
-rw-r--r--third_party/rust/memalloc/README.md26
-rw-r--r--third_party/rust/memalloc/src/lib.rs158
4 files changed, 195 insertions, 0 deletions
diff --git a/third_party/rust/memalloc/.cargo-checksum.json b/third_party/rust/memalloc/.cargo-checksum.json
new file mode 100644
index 0000000000..fb0b4b7c7c
--- /dev/null
+++ b/third_party/rust/memalloc/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"af07b00f080db01744f57056b0a4d44194afc07831d12aaa256f12ae22f9723d","README.md":"dc9539e01a85abc218e7e4fc1a2ee4512025a3ea6295a25ab50de91c3b500398","src/lib.rs":"4635b797b1b7d65f4c500b8e031715946c2631de8792b62bfc96ed79b4eee887"},"package":"df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"} \ No newline at end of file
diff --git a/third_party/rust/memalloc/Cargo.toml b/third_party/rust/memalloc/Cargo.toml
new file mode 100644
index 0000000000..bc4421c2cd
--- /dev/null
+++ b/third_party/rust/memalloc/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+
+name = "memalloc"
+version = "0.1.0"
+authors = ["Jonathan Reem <jonathan.reem@gmail.com>"]
+repository = "https://github.com/reem/rust-memalloc.git"
+description = "Memory allocation in stable rust."
+readme = "README.md"
+license = "MIT"
+
diff --git a/third_party/rust/memalloc/README.md b/third_party/rust/memalloc/README.md
new file mode 100644
index 0000000000..d2d0489009
--- /dev/null
+++ b/third_party/rust/memalloc/README.md
@@ -0,0 +1,26 @@
+# memalloc
+
+> Raw allocation APIs in stable rust.
+
+## [Documentation](https://crates.fyi/crates/memalloc/0.1.0)
+
+## Usage
+
+See the tests at the bottom of `src/lib.rs` for some examples.
+
+Use the crates.io repository; add this to your `Cargo.toml` along
+with the rest of your dependencies:
+
+```toml
+[dependencies]
+memalloc = "0.1"
+```
+
+## Author
+
+[Jonathan Reem](https://medium.com/@jreem) is the primary author and maintainer of memalloc.
+
+## License
+
+MIT
+
diff --git a/third_party/rust/memalloc/src/lib.rs b/third_party/rust/memalloc/src/lib.rs
new file mode 100644
index 0000000000..94cf7d2df7
--- /dev/null
+++ b/third_party/rust/memalloc/src/lib.rs
@@ -0,0 +1,158 @@
+#![cfg_attr(test, deny(warnings))]
+#![deny(missing_docs)]
+
+//! # memalloc
+//!
+//! Memory allocation in stable rust, providing a similar interface to `std::rt::heap`,
+//! notably these functions align everything according to the alignment of `u8`, rather
+//! than using a user-provided alignment.
+//!
+//! Additionally, they do not allow for handling allocation failure, and will simply
+//! abort the process on OOM. Unfortunately, this limitation is unavoidable if we want
+//! to use only stable APIs.
+//!
+
+use std::mem;
+
+/// Returns a pointer to `size` bytes of memory aligned to `mem::align_of::<u8>()`.
+///
+/// On failure, aborts the process.
+///
+/// Behavior is undefined if the requested size is 0.
+#[inline]
+pub unsafe fn allocate(size: usize) -> *mut u8 {
+ ptr_from_vec(Vec::with_capacity(size))
+}
+
+/// Resizes the allocation referenced by `ptr` to `new_size` bytes.
+///
+/// On failure, aborts the process.
+///
+/// If the allocation was relocated, the memory at the passed-in pointer is
+/// undefined after the call.
+///
+/// Behavior is undefined if the requested `new_size` is 0.
+///
+/// The `old_size` parameter is the size used to create the allocation
+/// referenced by `ptr`, or the `new_size` passed to previous reallocations.
+pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, new_size: usize) -> *mut u8 {
+ if old_size > new_size {
+ let mut buf = Vec::from_raw_parts(ptr, new_size, old_size);
+ buf.shrink_to_fit();
+
+ ptr_from_vec(buf)
+ } else if new_size > old_size {
+ let additional = new_size - old_size;
+
+ let mut buf = Vec::from_raw_parts(ptr, 0, old_size);
+ buf.reserve_exact(additional);
+
+ ptr_from_vec(buf)
+ } else {
+ ptr
+ }
+}
+
+/// Deallocates the memory referenced by `ptr`.
+///
+/// Behavior is undefined if `ptr` is null.
+///
+/// The `old_size` parameter is the size used to create the allocation
+/// referenced by `ptr`, or the `new_size` passed to the last reallocation.
+#[inline]
+pub unsafe fn deallocate(ptr: *mut u8, old_size: usize) {
+ Vec::from_raw_parts(ptr, 0, old_size);
+}
+
+/// A token empty allocation which cannot be read from or written to,
+/// but which can be used as a placeholder when a 0-sized allocation is
+/// required.
+pub fn empty() -> *mut u8 {
+ 1 as *mut u8
+}
+
+#[inline]
+fn ptr_from_vec(mut buf: Vec<u8>) -> *mut u8 {
+ let ptr = buf.as_mut_ptr();
+ mem::forget(buf);
+
+ ptr
+}
+
+#[cfg(test)]
+mod tests {
+ use std::ptr;
+ use {allocate, reallocate, deallocate, empty};
+
+ #[test]
+ fn test_empty() {
+ let ptr = empty();
+ assert!(ptr != ptr::null_mut());
+ }
+
+ #[test]
+ fn test_allocate() {
+ let buffer = unsafe { allocate(8) };
+
+ assert!(buffer != ptr::null_mut());
+
+ unsafe {
+ ptr::write(buffer.offset(0), 8);
+ ptr::write(buffer.offset(1), 4);
+ ptr::write(buffer.offset(3), 5);
+ ptr::write(buffer.offset(5), 3);
+ ptr::write(buffer.offset(7), 6);
+
+ assert_eq!(ptr::read(buffer.offset(0)), 8);
+ assert_eq!(ptr::read(buffer.offset(1)), 4);
+ assert_eq!(ptr::read(buffer.offset(3)), 5);
+ assert_eq!(ptr::read(buffer.offset(5)), 3);
+ assert_eq!(ptr::read(buffer.offset(7)), 6);
+ };
+
+ unsafe { deallocate(buffer, 8); }
+
+ // Try a large buffer
+ let buffer = unsafe { allocate(1024 * 1024) };
+ assert!(buffer != ptr::null_mut());
+
+ unsafe {
+ ptr::write(buffer.offset(1024 * 1024 - 1), 12);
+ assert_eq!(ptr::read(buffer.offset(1024 * 1024 - 1)), 12);
+ };
+
+ unsafe { deallocate(buffer, 1024 * 1024); }
+ }
+
+ #[test]
+ fn test_reallocate() {
+ let mut buffer = unsafe { allocate(8) };
+ assert!(buffer != ptr::null_mut());
+
+ buffer = unsafe { reallocate(buffer, 8, 16) };
+ assert!(buffer != ptr::null_mut());
+
+ unsafe {
+ // Put some data in the buffer
+ ptr::write(buffer.offset(0), 8);
+ ptr::write(buffer.offset(1), 4);
+ ptr::write(buffer.offset(5), 3);
+ ptr::write(buffer.offset(7), 6);
+ };
+
+ // Allocate so in-place fails.
+ unsafe { allocate(128) };
+
+ buffer = unsafe { reallocate(buffer, 16, 32) };
+ assert!(buffer != ptr::null_mut());
+
+ unsafe {
+ // Ensure the data is still there.
+ assert_eq!(ptr::read(buffer.offset(0)), 8);
+ assert_eq!(ptr::read(buffer.offset(1)), 4);
+ assert_eq!(ptr::read(buffer.offset(5)), 3);
+ assert_eq!(ptr::read(buffer.offset(7)), 6);
+ };
+ }
+}
+