[][src]Crate memory_slice

Structures and traits to represent and safely manipulate any data as raw memory

Examples

Any kind of data can be viewed as constant memory slice:

use memory_slice::AsMemory;
let v: [u8;4] = [1,1,1,1];
//as_memory return a &memory_slice
assert_eq!(unsafe{v.as_memory().read::<i32>()},1 + (1<<8) + (1<<16) + (1<<24));

But only types that does not preserve any invariants are accessible as mutable memory slice:

This will compile:

use memory_slice::AsMutMemory;
let mut v: [u8;4] = [1,1,1,1];
//as_memory return a &memory_slice
v.as_mut_memory().write(16 as u16);

This will not compile:

This example deliberately fails to compile
use memory_slice::AsMutMemory;
use std::string::String;
let mut v = String::new();
//as_memory return a &memory_slice
v.as_mut_memory().write(16 as u16);

Mutable memory slices can be used to write information of any type while preserving borrow rules. The API provide also a smart pointer that will drop value created on the memory slice:

use memory_slice::{align,AsMutMemory,AsMemory};
// creates an array of 64 u8 aligned as 8: 
let mut buff = align!(8,[0 as u8;64]);

//the create an int inside the buffer and get a reference to it
let (padding, v1, remaining_buffer) = buff.as_mut_memory().write(42 as i32);
assert!(padding.is_empty());
//unsafe{buff[0]}; //error => cannot borrow buff as immutable

//use the remaining unitialized buffer to write an u64 in it:
let (padding, v2, remaining_buffer2) = remaining_buffer.write(42 as u64);
assert_eq!(padding.len(), 4);
//unsafe{remaing_buffer.read::<u8>()}; //error => cannot borrow remaining_buffer

//v1 and v2 are reference to the i32 and u64 created inside buff
assert_eq!(*v1 as u64, *v2);

{
    extern crate alloc;
    use alloc::borrow::ToOwned;

    //In what remains of the buffer, let's create a value that needs to be dropped:
    let (_padding, v3, _remaining) = remaining_buffer2.emplace("42".to_owned());

    //v3 is a smart pointer to the String created in the buffer that will drop
    //this string when it goes out of scope
    assert_eq!(*v1, v3.parse::<i32>().unwrap());
} //string refered by v3 is dropped

//buff is not anymore borrowed, so it is accessible:
assert_eq!(unsafe { buff.as_memory().read::<i32>() }, 42);

//memory slice can be indexed (!!less inoffensive than it looks)
unsafe{*buff.as_mut_memory()[2..4].as_mut_unchecked()=16 as u16};
assert_ne!(unsafe { buff.as_memory().read::<i32>() }, 42);

A macro named buffer is provided to create un initialized buffer:

use memory_slice::buffer;
// create an uninitialized buffer of 64 bytes aligned as 8.
let mut buff = buffer!(64,8);
// buffer are dereferencable as memory_slice

//the create an int inside the buffer and get a reference to it
buff.write(42 as i32);

Macros

align

Returns an overaligned value.

buffer

Creates a statically sized buffer on the stack.

Structs

BufferAs

A buffer of uninitialized memory with same size and alignement as T.

Memory

Represents a raw memory range

OwnedRef

A reference that drops its pointee when it is dropped

OwnedSlice

A reference to a slice that drops its pointee when it is dropped

Traits

AsMemory

Enable conversion of any type to a constant memory slice

AsMutMemory

Enable conversion to a mutable memory.