[−][src]Struct avr_progmem::ProgMem
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,
T: Send,
impl<T> Sync for ProgMem<T> where
T: Sync,
T: Sync,
impl<T> Unpin for ProgMem<T> where
T: Unpin,
T: Unpin,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,