Skip to main content

libtw2_common/
bytes.rs

1use std::array::TryFromSliceError;
2use std::convert::TryInto;
3use std::mem;
4use zerocopy::byteorder::big_endian;
5
6pub trait TryFromByteSlice {
7    fn try_from_byte_slice(bytes: &[u8]) -> Result<&Self, TryFromSliceError>;
8}
9
10impl<const N: usize> TryFromByteSlice for [u8; N] {
11    fn try_from_byte_slice(bytes: &[u8]) -> Result<&[u8; N], TryFromSliceError> {
12        bytes.try_into()
13    }
14}
15
16pub trait ByteArray {
17    type ByteArray: AsRef<[u8]> + TryFromByteSlice;
18}
19
20pub trait AsBytesExt: ByteArray + zerocopy::AsBytes {
21    fn as_byte_array(&self) -> &Self::ByteArray {
22        TryFromByteSlice::try_from_byte_slice(self.as_bytes()).unwrap()
23    }
24}
25
26pub trait FromBytesExt: ByteArray + zerocopy::FromBytes {
27    fn ref_and_rest_from(bytes: &[u8]) -> Option<(&Self, &[u8])>
28    where
29        Self: Sized,
30    {
31        if bytes.len() < mem::size_of::<Self>() {
32            return None;
33        }
34        let (result, rest) = bytes.split_at(mem::size_of::<Self>());
35        Some((Self::ref_from(result).unwrap(), rest))
36    }
37    fn ref_from_array(bytes: &Self::ByteArray) -> &Self
38    where
39        Self: Sized,
40    {
41        Self::ref_from(bytes.as_ref()).unwrap()
42    }
43    fn from_array(bytes: Self::ByteArray) -> Self
44    where
45        Self: Copy + Sized,
46    {
47        *Self::ref_from_array(&bytes)
48    }
49}
50
51impl<T: ByteArray + zerocopy::AsBytes> AsBytesExt for T {}
52impl<T: ByteArray + zerocopy::FromBytes> FromBytesExt for T {}
53
54boilerplate_packed_internal!(big_endian::U32, 4, test_be_u32_size);