[][src]Struct avr_progmem::ProgMem

#[repr(transparent)]pub struct ProgMem<T>(_);

Best-effort safe wrapper around a value in program memory.

This type wraps a value that is stored in program memory, and offers safe functions to load those values from program memory into the data memory (or at least some registers).

Since its constructer is the single most critical point in its API, it is unsafe, despite it is supposed to be a safe wrapper (hence the 'best-effort' notation).

However, there is a rather simple way to make is sound, and that is defining the #[link_section = ".progmem"] (or ".text") on a static that contains this struct. And since its that simple, a macro progmem! is provided that will ensure this and should be always used to obtain a ProgMem instance in the first place.

Safety

This type is a best-effort safe, thus it interface with unsafe Rust given some invariants (like any other safe wrapper).

The important and obvious invariant is that all values of the struct (instances) must be stored in the program memory. Since that is a property that the compiler (as of now) can not determine or assert or anything, it can't even be asserted, so far, the constructor is the central most unsafe point of this type. But once established it can't change (for statics at least), thus the only unsafe part of this type is the constructor where the user has to guarantee that it is indeed stored in a static in progmem.

Notice that if you got a static mut it is unsafe from a start so such a safe wrapper is of little use, and still then has the problem, that it is totally unsound to move it out of the static (e.g. using std::mem::swap on it).

Therefore, only a immutable static in the correct memory segment can be considered to be a correct location for it.

Implementations

impl<T> ProgMem<T>[src]

pub const unsafe fn new(t: T) -> Self[src]

Construct a new instance of this type.

This struct is a wrapper type for data in the program code memory domain. Therefore when constructing this struct, it must be guaranteed to uphold this requirement! This contract is expressed by the fact that this function is unsafe. Also see the Safety section for details.

To simplify, there is a macro progmem! which creates a static and ensures that it is stored indeed in the program code memory domain, and then makes a call to this function to wrap that static. A user of this crate should always prefer using the progmem! macro to obtain a ProgMem value!

Safety

The ProgMem wrapper is build around the invariant that itself an thus its inner value are stored in the program code memory domain (on the AVR architecture).

That means that this function is only sound to call, if the value is stored in a static that is for instance attributed with #[link_section = ".progmem"].

However, the above requirement only applies to the AVR architecture (#[cfg(target_arch = "avr")]), because otherwise normal data access primitives are used. This means that the value must be stored in the regular data memory domain for ALL OTHER architectures! This still holds, even if such other architecture is of the Harvard architecture, because this is an AVR-only crate, not a general Harvard architecture crate!

impl<T: Copy> ProgMem<T>[src]

pub fn load(&self) -> T[src]

Read the inner value from progmem and return a regular value.

Panics

This method panics, if the size of the value (i.e. size_of::<T>()) is beyond 255 bytes. However, this is currently just a implementation limitation, which may be lifted in the future.

Also notice, if you really hit this limit, you would need 256+ bytes on your stack, on the Arduino Uno (at least) that means that you might be close to stack overflow. Thus it might be better to restructure your data, so you can store it as an array of something, than you can use the load_at and load_sub_array methods instead.

pub fn ptr(&self) -> *const T[src]

Return the raw pointer to the inner value.

Notice that the returned pointer is indeed a pointer into the progmem domain! It may never be dereferenced via the default Rust operations. That means a unsafe{*pm.get_inner_ptr()} is undefined behavior!

impl<T: Copy, const N: usize> ProgMem<[T; N]>[src]

Utilities to work with an array in progmem.

pub fn load_at(&self, idx: usize) -> T[src]

Load a single element from the inner array.

This method is analog to a slice indexing self.inner[idx], so the same requirements apply, like the index idx should be less then the length N of the array, otherwise a panic will be risen.

Panics

This method panics, if the given index idx is grater or equal to the length N of the inner type.

This method also panics, if the size of the value (i.e. size_of::<T>()) is beyond 255 bytes. However, this is currently just a implementation limitation, which may be lifted in the future.

pub fn load_sub_array<const M: usize>(&self, start_idx: usize) -> [T; M][src]

Loads a sub array from the inner array.

This method is analog to a sub-slicing self.inner[idx..(idx+M)] but returning an owned array instead of a slice, simply because it has to copy the data anyway from the progmem into the data domain (i.e. the stack).

Also notice, that since this crate is intended for AVR micro-controllers, static arrays are generally preferred over dynamically allocated types such as a Vec (as of now (mid-2020) there isn't even a good way to get a Vec on AVR in Rust).

Panics

This method panics, if the given index idx is grater or equal to the length N of the inner array, or the end index idx+M is grater than the length N of the inner array.

This method also panics, if the size of the value (i.e. size_of::<[T;M]>()) is beyond 255 bytes. However, this is currently just a implementation limitation, which may be lifted in the future.

Auto Trait Implementations

impl<T> Send for ProgMem<T> where
    T: Send

impl<T> Sync for ProgMem<T> where
    T: Sync

impl<T> Unpin for ProgMem<T> where
    T: Unpin

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.