[][src]Crate 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);
}

Modules

base

Defines the BaseArray struct.

impls

Implementations of safe APIs to the BaseArray struct.

naive_rc

This module contains naively reference counted arrays, both as atomic and regular versions; i.e. if you're not careful, you could make a cycle that never gets deallocated.

Traits

Container

Trait for a simple container.

CopyMap

Trait for a container indexed by a value that implements Copy and Eq.

DefaultLabelledArray

Trait for a labelled array with a default value.

LabelledArray

Array with an optional label struct stored next to the data.

LabelledArrayMut

Array with optional label struct stored next to the data that can be mutated

MakeArray

An array of arbitrary (sized) values that can be safely initialized.

SliceArray

Array that returns a slice into its contents

SliceArrayMut

Array that returns a mutable slice into its contents

Type Definitions

HeapArray

2-word reference to an array on the heap that takes ownership of its contained data.