use core::convert::TryFrom;
use super::super::{Field, StorageIntoFieldView, StorageToFieldView};
use super::PrimitiveField;
use crate::endianness::Endianness;
use crate::utils::data::Data;
pub trait FieldSliceAccess<'a>: Field {
type SliceType: 'a;
type MutSliceType: 'a;
fn data(storage: &'a [u8]) -> Self::SliceType;
fn data_mut(storage: &'a mut [u8]) -> Self::MutSliceType;
}
impl<'a, E: Endianness, const OFFSET_: usize> FieldSliceAccess<'a>
for PrimitiveField<[u8], E, OFFSET_>
{
type SliceType = &'a [u8];
type MutSliceType = &'a mut [u8];
#[inline(always)]
fn data(storage: &'a [u8]) -> &'a [u8] {
&storage[Self::OFFSET..]
}
#[inline(always)]
fn data_mut(storage: &'a mut [u8]) -> &'a mut [u8] {
&mut storage[Self::OFFSET..]
}
}
impl<E: Endianness, const OFFSET_: usize> Field for PrimitiveField<[u8], E, OFFSET_> {
type Endian = E;
const OFFSET: usize = OFFSET_;
const SIZE: Option<usize> = None;
}
impl<'a, E: Endianness, const OFFSET_: usize> StorageToFieldView<&'a [u8]>
for PrimitiveField<[u8], E, OFFSET_>
{
type View = &'a [u8];
#[inline(always)]
fn view(storage: &'a [u8]) -> Self::View {
&storage[Self::OFFSET..]
}
}
impl<'a, E: Endianness, const OFFSET_: usize> StorageToFieldView<&'a mut [u8]>
for PrimitiveField<[u8], E, OFFSET_>
{
type View = &'a mut [u8];
#[inline(always)]
fn view(storage: &'a mut [u8]) -> Self::View {
&mut storage[Self::OFFSET..]
}
}
impl<S: AsRef<[u8]>, E: Endianness, const OFFSET_: usize> StorageIntoFieldView<S>
for PrimitiveField<[u8], E, OFFSET_>
{
type View = Data<S>;
#[inline(always)]
fn into_view(storage: S) -> Self::View {
Data::from(storage).into_subregion(Self::OFFSET..)
}
}
impl<'a, E: Endianness, const N: usize, const OFFSET_: usize> FieldSliceAccess<'a>
for PrimitiveField<[u8; N], E, OFFSET_>
{
type SliceType = &'a [u8; N];
type MutSliceType = &'a mut [u8; N];
#[inline(always)]
fn data(storage: &'a [u8]) -> &'a [u8; N] {
<&[u8; N]>::try_from(&storage[Self::OFFSET..(Self::OFFSET + N)]).unwrap()
}
#[inline(always)]
fn data_mut(storage: &'a mut [u8]) -> &'a mut [u8; N] {
<&mut [u8; N]>::try_from(&mut storage[Self::OFFSET..(Self::OFFSET + N)]).unwrap()
}
}
impl<E: Endianness, const N: usize, const OFFSET_: usize> Field
for PrimitiveField<[u8; N], E, OFFSET_>
{
type Endian = E;
const OFFSET: usize = OFFSET_;
const SIZE: Option<usize> = Some(N);
}
impl<'a, E: Endianness, const N: usize, const OFFSET_: usize> StorageToFieldView<&'a [u8]>
for PrimitiveField<[u8; N], E, OFFSET_>
{
type View = &'a [u8; N];
#[inline(always)]
fn view(storage: &'a [u8]) -> Self::View {
Self::View::try_from(&storage[Self::OFFSET..(Self::OFFSET + N)]).unwrap()
}
}
impl<'a, E: Endianness, const N: usize, const OFFSET_: usize> StorageToFieldView<&'a mut [u8]>
for PrimitiveField<[u8; N], E, OFFSET_>
{
type View = &'a mut [u8; N];
#[inline(always)]
fn view(storage: &'a mut [u8]) -> Self::View {
Self::View::try_from(&mut storage[Self::OFFSET..(Self::OFFSET + N)]).unwrap()
}
}
impl<S: AsRef<[u8]>, E: Endianness, const N: usize, const OFFSET_: usize> StorageIntoFieldView<S>
for PrimitiveField<[u8; N], E, OFFSET_>
{
type View = Data<S>;
#[inline(always)]
fn into_view(storage: S) -> Self::View {
Data::from(storage).into_subregion(Self::OFFSET..(Self::OFFSET + N))
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::float_cmp)]
use crate::prelude::*;
use crate::PrimitiveField;
#[test]
fn test_slice() {
let mut storage = vec![0; 1024];
type Field1 = PrimitiveField<[u8], LittleEndian, 5>;
type Field2 = PrimitiveField<[u8], BigEndian, 7>;
Field1::data_mut(&mut storage)[..5].copy_from_slice(&[10, 20, 30, 40, 50]);
Field2::data_mut(&mut storage)[..5].copy_from_slice(&[60, 70, 80, 90, 100]);
assert_eq!(&[10, 20, 60, 70, 80], &Field1::data(&storage)[..5]);
assert_eq!(&[60, 70, 80, 90, 100], &Field2::data(&storage)[..5]);
let _a: &[u8] = Field1::data(&storage);
let _b: &mut [u8] = Field1::data_mut(&mut storage);
}
#[test]
fn test_array() {
let mut storage = vec![0; 1024];
type Field1 = PrimitiveField<[u8; 2], LittleEndian, 5>;
type Field2 = PrimitiveField<[u8; 5], BigEndian, 6>;
Field1::data_mut(&mut storage).copy_from_slice(&[10, 20]);
Field2::data_mut(&mut storage).copy_from_slice(&[60, 70, 80, 90, 100]);
assert_eq!(&[10, 60], Field1::data(&storage));
assert_eq!(&[60, 70, 80, 90, 100], Field2::data(&storage));
assert_eq!(Some(2), PrimitiveField::<[u8; 2], LittleEndian, 5>::SIZE);
assert_eq!(Some(5), PrimitiveField::<[u8; 5], BigEndian, 5>::SIZE);
let _a: &[u8; 2] = Field1::data(&storage);
let _b: &mut [u8; 2] = Field1::data_mut(&mut storage);
}
}