use crate::{LayoutType, MemLoc, MemLocType, Word};
use core::borrow::Borrow;
use core::ops::Index;
use core::ops::IndexMut;
use core::ops::Range;
pub const WORD_SIZE: usize = core::mem::size_of::<Word>();
const fn check_range_bounds<const ARR: usize, const ADDR: usize, const SIZE: usize>() -> Range<usize> {
assert!(
ARR >= ADDR + SIZE,
"ARR length must be greater than or equal to sub arrays ADDR + SIZE"
);
ADDR..ADDR + SIZE
}
pub(super) trait SubArray<const ARR: usize, const ADDR: usize, const SIZE: usize>:
Index<Range<usize>, Output = [u8]>
{
const RANGE: Range<usize> = check_range_bounds::<ARR, ADDR, SIZE>();
fn sub_array(&self) -> [u8; SIZE] {
self[Self::RANGE]
.try_into()
.expect("This can't ever fail due to the compile-time check")
}
fn sized_slice(&self) -> &[u8; SIZE] {
(&self[Self::RANGE])
.try_into()
.expect("This can't ever fail due to the compile-time check")
}
}
pub(super) trait SubArrayMut<const ARR: usize, const ADDR: usize, const SIZE: usize>:
SubArray<ARR, ADDR, SIZE> + IndexMut<Range<usize>>
{
fn sized_slice_mut(&mut self) -> &mut [u8; SIZE] {
(&mut self[Self::RANGE])
.try_into()
.expect("This can't ever fail due to the compile-time check")
}
}
impl<const ARR: usize, const ADDR: usize, const SIZE: usize> SubArray<ARR, ADDR, SIZE> for [u8; ARR] {}
impl<const ARR: usize, const ADDR: usize, const SIZE: usize> SubArrayMut<ARR, ADDR, SIZE> for [u8; ARR] {}
pub fn store_number_at<const ARR: usize, const ADDR: usize, const SIZE: usize, T>(
buf: &mut [u8; ARR],
layout: LayoutType<ADDR, SIZE, T>,
number: T::Type,
) where
T: MemLocType<ADDR, SIZE>,
<T as MemLocType<ADDR, SIZE>>::Type: Into<Word>,
{
from_loc_mut(layout.loc(), buf).copy_from_slice(&number.into().to_be_bytes());
}
pub fn restore_number_at<const ARR: usize, const ADDR: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, WORD_SIZE, T>,
) -> T::Type
where
T: MemLocType<ADDR, WORD_SIZE>,
Word: Into<<T as MemLocType<ADDR, WORD_SIZE>>::Type>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf)).into()
}
pub fn restore_word_at<const ARR: usize, const ADDR: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, WORD_SIZE, T>,
) -> Word
where
T: MemLocType<ADDR, WORD_SIZE, Type = Word>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf))
}
pub fn restore_u8_at<const ARR: usize, const ADDR: usize, T>(buf: &[u8; ARR], loc: LayoutType<ADDR, WORD_SIZE, T>) -> u8
where
T: MemLocType<ADDR, WORD_SIZE, Type = u8>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf)) as u8
}
pub fn restore_u16_at<const ARR: usize, const ADDR: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, WORD_SIZE, T>,
) -> u16
where
T: MemLocType<ADDR, WORD_SIZE, Type = u16>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf)) as u16
}
pub fn restore_u32_at<const ARR: usize, const ADDR: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, WORD_SIZE, T>,
) -> u32
where
T: MemLocType<ADDR, WORD_SIZE, Type = u32>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf)) as u32
}
pub fn restore_usize_at<const ARR: usize, const ADDR: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, WORD_SIZE, T>,
) -> usize
where
T: MemLocType<ADDR, WORD_SIZE, Type = Word>,
{
Word::from_be_bytes(from_loc(loc.loc(), buf)) as usize
}
pub fn store_at<const ARR: usize, const ADDR: usize, const SIZE: usize, T>(
buf: &mut [u8; ARR],
layout: LayoutType<ADDR, SIZE, T>,
array: &[u8; SIZE],
) where
T: MemLocType<ADDR, SIZE>,
<T as MemLocType<ADDR, SIZE>>::Type: Borrow<[u8; SIZE]>,
{
from_loc_mut(layout.loc(), buf).copy_from_slice(array);
}
pub fn restore_at<const ARR: usize, const ADDR: usize, const SIZE: usize, T>(
buf: &[u8; ARR],
loc: LayoutType<ADDR, SIZE, T>,
) -> [u8; SIZE]
where
T: MemLocType<ADDR, SIZE>,
[u8; SIZE]: From<<T as MemLocType<ADDR, SIZE>>::Type>,
{
from_loc(loc.loc(), buf)
}
pub fn from_array<const ARR: usize, const SIZE: usize>(buf: &[u8; ARR]) -> [u8; SIZE] {
SubArray::<ARR, 0, SIZE>::sub_array(buf)
}
pub fn from_loc<const ARR: usize, const ADDR: usize, const SIZE: usize>(
_layout: MemLoc<ADDR, SIZE>,
buf: &[u8; ARR],
) -> [u8; SIZE] {
SubArray::<ARR, ADDR, SIZE>::sub_array(buf)
}
pub fn from_array_ref<const ARR: usize, const SIZE: usize>(buf: &[u8; ARR]) -> &[u8; SIZE] {
SubArray::<ARR, 0, SIZE>::sized_slice(buf)
}
pub fn from_array_mut<const ARR: usize, const SIZE: usize>(buf: &mut [u8; ARR]) -> &mut [u8; SIZE] {
SubArrayMut::<ARR, 0, SIZE>::sized_slice_mut(buf)
}
pub fn from_loc_ref<const ARR: usize, const ADDR: usize, const SIZE: usize>(
_layout: MemLoc<ADDR, SIZE>,
buf: &[u8; ARR],
) -> &[u8; SIZE] {
SubArray::<ARR, ADDR, SIZE>::sized_slice(buf)
}
pub fn from_loc_mut<const ARR: usize, const ADDR: usize, const SIZE: usize>(
_layout: MemLoc<ADDR, SIZE>,
buf: &mut [u8; ARR],
) -> &mut [u8; SIZE] {
SubArrayMut::<ARR, ADDR, SIZE>::sized_slice_mut(buf)
}