#array #heap #heap-memory #dyn-sized-types

heaparray

Flexible support for dynamically-sized types, using heap-allocated array of structs

2 releases

0.5.1 Jul 2, 2019
0.5.0 Jun 17, 2019
0.4.3 Jun 2, 2019
0.4.2 May 23, 2019
0.1.6 May 12, 2019

#515 in Memory management

MIT license

78KB
1.5K SLoC

heaparray

This crate aims to give people better control of how they allocate memory, by providing a customizable way to allocate blocks of memory, that optionally contains metadata about the block itself. This makes it much easier to implement Dynamically-Sized Types (DSTs), and also reduces the number of pointer indirections necessary to share data between threads.

Features

  • Safe API to dynamically-sized types
  • Generic implementations of common tasks so you can customize the implementation of a type without having to write additional boilerplate
  • Atomically reference-counted memory blocks of arbitrary size without using a Vec; this means you can access reference-counted memory with only a single pointer indirection.

Examples

Creating an array:

use heaparray::*;
let len = 10;
let array = HeapArray::new(len, |idx| idx + 3);
assert!(array[1] == 4);

Indexing works as you would expect:

use heaparray::*;
let mut array = HeapArray::new(10, |_| 0);
array[3] = 2;
assert!(array[3] == 2);

Additionally, you can customize what information should be stored alongside the elements in the array using the HeapArray::with_label function:

struct MyLabel {
    pub even: usize,
    pub odd: usize,
}

let array = HeapArray::with_label(
    MyLabel { even: 0, odd: 0 },
    100,
    |label, index| {
        if index % 2 == 0 {
            label.even += 1;
            index
        } else {
            label.odd += 1;
            index
        }
    });

Dynamically Sized Types

The Rust documentation on exotically sized types, at the end of the section on dynamically-sized types states that:

Currently the only properly supported way to create a custom DST is by making your type generic and performing an unsizing coercion... (Yes, custom DSTs are a largely half-baked feature for now.)

This crate aims to provide some of that functionality; the code that the docs give is the following:

struct MySuperSliceable<T: ?Sized> {
    info: u32,
    data: T
}

fn main() {
    let sized: MySuperSliceable<[u8; 8]> = MySuperSliceable {
        info: 17,
        data: [0; 8],
    };

    let dynamic: &MySuperSliceable<[u8]> = &sized;

    // prints: "17 [0, 0, 0, 0, 0, 0, 0, 0]"
    println!("{} {:?}", dynamic.info, &dynamic.data);
}

using this crate, the MySuperSliceable<[u8]> type would be implemented like this:

use heaparray::*;

type MySuperSliceable = HeapArray<u8, u32>;

fn main() {
    let info = 17;
    let len = 8;
    let dynamic = MySuperSliceable::with_label(info, len, |_,_| 0);
    println!("{:?}", dynamic);
}

License: MIT

Dependencies