packed_struct/
packing.rs

1use crate::internal_prelude::v1::*;
2
3use crate::types_bits::ByteArray;
4
5/// A structure that can be packed and unpacked from a byte array.
6/// 
7/// In case the structure occupies less bits than there are in the byte array,
8/// the packed that should be aligned to the end of the array, with leading bits
9/// being ignored.
10/// 
11/// 10 bits packs into: [0b00000011, 0b11111111]
12pub trait PackedStruct where Self: Sized {
13    /// The appropriately sized byte array into which this structure will be packed, for example [u8; 2]. 
14    type ByteArray : ByteArray;
15    
16    /// Packs the structure into a byte array.
17    fn pack(&self) -> PackingResult<Self::ByteArray>;
18    /// Unpacks the structure from a byte array.
19    fn unpack(src: &Self::ByteArray) -> PackingResult<Self>;
20}
21
22/// Infos about a particular type that can be packaged.
23pub trait PackedStructInfo {
24    /// Number of bits that this structure occupies when being packed.
25    fn packed_bits() -> usize;
26}
27
28/// A structure that can be packed and unpacked from a slice of bytes.
29pub trait PackedStructSlice where Self: Sized {
30    /// Pack the structure into an output buffer.
31    fn pack_to_slice(&self, output: &mut [u8]) -> PackingResult<()>;
32    /// Unpack the structure from a buffer.
33    fn unpack_from_slice(src: &[u8]) -> PackingResult<Self>;
34    /// Number of bytes that the type or this particular instance of this structure demands for packing or unpacking.
35    fn packed_bytes_size(opt_self: Option<&Self>) -> PackingResult<usize>;
36
37    #[cfg(any(feature="alloc", feature="std"))]
38    fn pack_to_vec(&self) -> PackingResult<Vec<u8>> {
39        let size = Self::packed_bytes_size(Some(self))?;
40        let mut buf = vec![0; size];
41        self.pack_to_slice(&mut buf)?;
42        Ok(buf)
43    }
44}
45
46#[cfg_attr(feature = "use_serde", derive(Serialize, Deserialize))]
47#[derive(Debug, Copy, Clone, PartialEq, Eq)]
48/// Packing errors that might occur during packing or unpacking
49pub enum PackingError {
50    InvalidValue,
51    BitsError,
52    BufferTooSmall,
53    NotImplemented,
54    InstanceRequiredForSize,
55    MoreThanOneDynamicType,
56    BufferSizeMismatch { expected: usize, actual: usize },
57    BufferModMismatch { actual_size: usize, modulo_required: usize },
58    SliceIndexingError { slice_len: usize },
59    InternalError
60}
61
62impl crate::Display for PackingError {
63    fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
64        write!(f, "{:?}", self)
65    }    
66}
67
68#[cfg(feature="std")]
69impl ::std::error::Error for PackingError {
70    fn description(&self) -> &str {
71        match *self {
72            PackingError::InvalidValue => "Invalid value",
73            PackingError::BitsError => "Bits error",
74            PackingError::BufferTooSmall => "Buffer too small",            
75            PackingError::BufferSizeMismatch { .. } => "Buffer size mismatched",
76            PackingError::NotImplemented => "Not implemented",
77            PackingError::InstanceRequiredForSize => "This structure's packing size can't be determined statically, an instance is required.",
78            PackingError::BufferModMismatch { .. } => "The structure's size is not a multiple of the item's size",
79            PackingError::SliceIndexingError { .. } => "Failed to index into a slice",
80            PackingError::MoreThanOneDynamicType => "Only one dynamically sized type is supported in the tuple",
81            PackingError::InternalError => "Internal error"
82        }
83    }
84}
85
86impl From<PackingError> for crate::fmt::Error {
87    fn from(_: PackingError) -> Self {
88        Self
89    }
90}
91
92pub type PackingResult<T> = Result<T, PackingError>;