1#![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 fn pack(&self, dst: &mut [u8]) -> Result<usize, BitWrapError>;
51
52 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}