bitwrap/
lib.rs

1//! # bitwrap
2//!
3//! [![docs](https://docs.rs/bitwrap/badge.svg)](https://docs.rs/bitwrap)
4//!
5//! ## Intro
6//!
7//! bitwrap is a derive macro and interface to declare a struct data member
8//! with explicit size, in bits.
9
10#![cfg_attr(not(feature = "std"), no_std)]
11
12
13use {
14    core::{
15        fmt,
16        convert::Infallible,
17    },
18};
19
20
21pub use {
22    bitwrap_derive::BitWrap,
23};
24
25
26#[derive(Debug, PartialEq)]
27pub struct BitWrapError;
28
29
30impl fmt::Display for BitWrapError {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        write!(f, "index out of bounds")
33    }
34}
35
36
37#[cfg(feature = "std")]
38impl std::error::Error for BitWrapError {}
39
40
41impl From<Infallible> for BitWrapError {
42    fn from(x: Infallible) -> BitWrapError {
43        match x {}
44    }
45}
46
47
48pub trait BitWrapExt {
49    /// Build byte array
50    fn pack(&self, dst: &mut [u8]) -> Result<usize, BitWrapError>;
51
52    /// Extract object field values from byte array
53    fn unpack(&mut self, src: &[u8]) -> Result<usize, BitWrapError>;
54}
55
56
57#[cfg(feature = "std")]
58impl BitWrapExt for Vec<u8> {
59    #[inline]
60    fn pack(&self, dst: &mut [u8]) -> Result<usize, BitWrapError> {
61        let len = self.len();
62        if dst.len() >= len {
63            dst[.. len].clone_from_slice(self.as_slice());
64            Ok(len)
65        } else {
66            Err(BitWrapError)
67        }
68    }
69
70    #[inline]
71    fn unpack(&mut self, src: &[u8]) -> Result<usize, BitWrapError> {
72        self.extend_from_slice(src);
73        Ok(src.len())
74    }
75}
76
77
78#[cfg(feature = "std")]
79impl<T: BitWrapExt + Default> BitWrapExt for Vec<T> {
80    #[inline]
81    fn pack(&self, dst: &mut [u8]) -> Result<usize, BitWrapError> {
82        let mut skip = 0;
83        for item in self {
84            skip += item.pack(&mut dst[skip ..])?;
85        }
86        Ok(skip)
87    }
88
89    #[inline]
90    fn unpack(&mut self, src: &[u8]) -> Result<usize, BitWrapError> {
91        let mut skip = 0;
92        while skip < src.len() {
93            let mut item = T::default();
94            skip += item.unpack(&src[skip ..])?;
95            self.push(item);
96        }
97        Ok(skip)
98    }
99}
100
101
102#[cfg(feature = "std")]
103impl BitWrapExt for String {
104    #[inline]
105    fn pack(&self, dst: &mut [u8]) -> Result<usize, BitWrapError> {
106        let s = self.as_bytes();
107        let len = s.len();
108        if dst.len() >= len {
109            dst[.. len].clone_from_slice(s);
110            Ok(len)
111        } else {
112            Err(BitWrapError)
113        }
114    }
115
116    #[inline]
117    fn unpack(&mut self, src: &[u8]) -> Result<usize, BitWrapError> {
118        let s = match std::str::from_utf8(src) {
119            Ok(v) => v,
120            Err(_) => return Err(BitWrapError),
121        };
122
123        self.push_str(s);
124        Ok(src.len())
125    }
126}