8 unstable releases (3 breaking)

0.4.2 Sep 20, 2023
0.4.1 Sep 19, 2023
0.3.1 Aug 31, 2023
0.2.0 Aug 29, 2023
0.1.2 Aug 28, 2023

#178 in Memory management

MIT OR Apache-2.0 OR Zlib

120KB
2K SLoC

contiguous_mem

contiguous_mem streamlines storage and management of data stored in contiguous blocks of memory.

Crate Documentation CI Status Zlib or MIT or Apache 2.0 license

Key Features

  • no_std support!
  • Simple and straightforward interface similar to standard containers.
  • Support for dynamic resizing of allocated memory keeping the created references functional (for safe implementations).

Specialized implementations

You can pick and choose which implementation suits your use case best allowing you to avoid runtime cost of synchronization and additionally memory cost of safely wrapping referenced data if you don't need it.

Default implementation keeps relative offsets of stored data which are resolved on access.

Use cases

  • Storing differently typed/sized data. (example)
  • Ensuring stored data is placed adjacently in memory. (example)
    • Note that returned references are not contiguous, only data they refer to is.

Getting Started

Add the crate to your dependencies:

[dependencies]
contiguous_mem = { version = "0.4" }

Optionally enable no_std feature to use in no_std environment:

[dependencies]
contiguous_mem = { version = "0.4", features = ["no_std"] }

Features

  • no_std - enables no_std dependencies for atomics, mutexes and rwlocks
  • debug - enables derive(Debug) on structures unrelated to error handling
  • ptr_metadata <nightly> - allows casting references into dyn Trait
  • error_in_core <nightly> - enables support for core::error::Error in no_std environment

Usage

use contiguous_mem::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Data {
    value: u32,
}

fn main() {
    // Create a ContiguousMemory instance with a capacity of 1024 bytes and 1-byte alignment
    let mut memory = ContiguousMemory::new(1024);

    // Store data in the memory container
    let data = Data { value: 42 };
    let stored_number: ContiguousMemoryRef<u64> = memory.push(22u64);
    let stored_data: ContiguousMemoryRef<Data> = memory.push(data);

    // Retrieve and use the stored data
    assert_eq!(*stored_data.get(), data);
    assert_eq!(*stored_number.get(), 22);
}
  • References have a similar API as RefCell

Note that reference types returned by store are inferred and only shown here for demonstration purposes.

For more usage examples see the examples directory.

Stability

All versions prior to 1.0.0 are not considered production ready. This is my first crate and there's still a lot of edge cases I didn't get a chance to consider yet.

Prelimenary tests are in place but I don't consider them sufficient to guarantee full correctness of behavior. I am however using this crate for development of another crate which allows me to do some integration testing besides just examples.

Alternatives

  • manually managing memory to ensure contiguous placement of data
    • prone to errors and requires unsafe code
  • for storing types with uniform Layout, when you only need to erase their types at the container level see:
  • using a custom allocator like blink-alloc to ensure contiguous placement of data
    • requires allocator_api feature
    • blink-alloc provides a similar functionality as this crate without the allocator_api feature; intended for use in loops so it doesn't support freeing some values while retaining other

Contributions

Contributions are welcome, feel free to create an issue or a pull request.

All contributions to the project are licensed under the Zlib/MIT/Apache 2.0 license unless you explicitly state otherwise.

License

This project is licensed under Zlib, MIT, or Apache-2.0 license, choose whichever suits you most.

Dependencies

~0–300KB