1#![cfg_attr(not(feature = "std"), no_std)]
15
16#[cfg(not(feature = "std"))]
17extern crate alloc;
18
19#[cfg(not(feature = "std"))]
20use alloc::{format, string::String, vec::Vec};
21use core::{cmp::min, fmt, ops};
22
23pub struct PrettySlice<'a>(&'a [u8]);
25
26impl<'a> fmt::Debug for PrettySlice<'a> {
27 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28 for i in 0..self.0.len() {
29 if i > 0 {
30 write!(f, "ยท{:02x}", self.0[i])?;
31 } else {
32 write!(f, "{:02x}", self.0[i])?;
33 }
34 }
35 Ok(())
36 }
37}
38
39impl<'a> fmt::Display for PrettySlice<'a> {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 for i in 0..self.0.len() {
42 write!(f, "{:02x}", self.0[i])?;
43 }
44 Ok(())
45 }
46}
47
48pub trait ToPretty {
51 fn pretty(&self) -> PrettySlice<'_>;
53 fn to_hex(&self) -> String {
55 format!("{}", self.pretty())
56 }
57}
58
59impl<T: AsRef<[u8]>> ToPretty for T {
60 fn pretty(&self) -> PrettySlice<'_> {
61 PrettySlice(self.as_ref())
62 }
63}
64
65pub enum BytesRef<'a> {
67 Flexible(&'a mut Bytes),
69 Fixed(&'a mut [u8]),
71}
72
73impl<'a> BytesRef<'a> {
74 pub fn write(&mut self, offset: usize, input: &[u8]) -> usize {
78 match *self {
79 BytesRef::Flexible(ref mut data) => {
80 let data_len = data.len();
81 let wrote = input.len() + if data_len > offset { 0 } else { offset - data_len };
82
83 data.resize(offset, 0);
84 data.extend_from_slice(input);
85 wrote
86 }
87 BytesRef::Fixed(ref mut data) if offset < data.len() => {
88 let max = min(data.len() - offset, input.len());
89 data[offset..(max + offset)].copy_from_slice(&input[..max]);
90 max
91 }
92 _ => 0,
93 }
94 }
95}
96
97impl<'a> ops::Deref for BytesRef<'a> {
98 type Target = [u8];
99
100 fn deref(&self) -> &[u8] {
101 match *self {
102 BytesRef::Flexible(ref bytes) => bytes,
103 BytesRef::Fixed(ref bytes) => bytes,
104 }
105 }
106}
107
108impl<'a> ops::DerefMut for BytesRef<'a> {
109 fn deref_mut(&mut self) -> &mut [u8] {
110 match *self {
111 BytesRef::Flexible(ref mut bytes) => bytes,
112 BytesRef::Fixed(ref mut bytes) => bytes,
113 }
114 }
115}
116
117pub type Bytes = Vec<u8>;
119
120#[cfg(test)]
121mod tests {
122 use super::BytesRef;
123 #[cfg(not(feature = "std"))]
124 use alloc::vec;
125
126 #[test]
127 fn should_write_bytes_to_fixed_bytesref() {
128 let mut data1 = vec![0, 0, 0];
130 let mut data2 = vec![0, 0, 0];
131 let (res1, res2) = {
132 let mut bytes1 = BytesRef::Fixed(&mut data1[..]);
133 let mut bytes2 = BytesRef::Fixed(&mut data2[1..2]);
134
135 let res1 = bytes1.write(1, &[1, 1, 1]);
137 let res2 = bytes2.write(3, &[1, 1, 1]);
138 (res1, res2)
139 };
140
141 assert_eq!(&data1, &[0, 1, 1]);
143 assert_eq!(res1, 2);
144
145 assert_eq!(&data2, &[0, 0, 0]);
146 assert_eq!(res2, 0);
147 }
148
149 #[test]
150 fn should_write_bytes_to_flexible_bytesref() {
151 let mut data1 = vec![0, 0, 0];
153 let mut data2 = vec![0, 0, 0];
154 let mut data3 = vec![0, 0, 0];
155 let (res1, res2, res3) = {
156 let mut bytes1 = BytesRef::Flexible(&mut data1);
157 let mut bytes2 = BytesRef::Flexible(&mut data2);
158 let mut bytes3 = BytesRef::Flexible(&mut data3);
159
160 let res1 = bytes1.write(1, &[1, 1, 1]);
162 let res2 = bytes2.write(3, &[1, 1, 1]);
163 let res3 = bytes3.write(5, &[1, 1, 1]);
164 (res1, res2, res3)
165 };
166
167 assert_eq!(&data1, &[0, 1, 1, 1]);
169 assert_eq!(res1, 3);
170
171 assert_eq!(&data2, &[0, 0, 0, 1, 1, 1]);
172 assert_eq!(res2, 3);
173
174 assert_eq!(&data3, &[0, 0, 0, 0, 0, 1, 1, 1]);
175 assert_eq!(res3, 5);
176 }
177}