1use std::fmt;
23use std::cmp::min;
24use std::ops::{Deref, DerefMut};
25
26pub struct PrettySlice<'a> (&'a [u8]);
28
29impl<'a> fmt::Debug for PrettySlice<'a> {
30 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31 for i in 0..self.0.len() {
32 match i > 0 {
33 true => { write!(f, "ยท{:02x}", self.0[i])?; },
34 false => { write!(f, "{:02x}", self.0[i])?; },
35 }
36 }
37 Ok(())
38 }
39}
40
41impl<'a> fmt::Display for PrettySlice<'a> {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 for i in 0..self.0.len() {
44 write!(f, "{:02x}", self.0[i])?;
45 }
46 Ok(())
47 }
48}
49
50pub trait ToPretty {
53 fn pretty(&self) -> PrettySlice;
55 fn to_hex(&self) -> String {
57 format!("{}", self.pretty())
58 }
59}
60
61impl<T: AsRef<[u8]>> ToPretty for T {
62 fn pretty(&self) -> PrettySlice {
63 PrettySlice(self.as_ref())
64 }
65}
66
67pub enum BytesRef<'a> {
69 Flexible(&'a mut Bytes),
71 Fixed(&'a mut [u8])
73}
74
75impl<'a> BytesRef<'a> {
76 pub fn write(&mut self, offset: usize, input: &[u8]) -> usize {
80 match *self {
81 BytesRef::Flexible(ref mut data) => {
82 let data_len = data.len();
83 let wrote = input.len() + if data_len > offset { 0 } else { offset - data_len };
84
85 data.resize(offset, 0);
86 data.extend_from_slice(input);
87 wrote
88 },
89 BytesRef::Fixed(ref mut data) if offset < data.len() => {
90 let max = min(data.len() - offset, input.len());
91 for i in 0..max {
92 data[offset + i] = input[i];
93 }
94 max
95 },
96 _ => 0
97 }
98 }
99}
100
101impl<'a> Deref for BytesRef<'a> {
102 type Target = [u8];
103
104 fn deref(&self) -> &[u8] {
105 match *self {
106 BytesRef::Flexible(ref bytes) => bytes,
107 BytesRef::Fixed(ref bytes) => bytes,
108 }
109 }
110}
111
112impl <'a> DerefMut for BytesRef<'a> {
113 fn deref_mut(&mut self) -> &mut [u8] {
114 match *self {
115 BytesRef::Flexible(ref mut bytes) => bytes,
116 BytesRef::Fixed(ref mut bytes) => bytes,
117 }
118 }
119}
120
121pub type Bytes = Vec<u8>;
123
124#[cfg(test)]
125mod tests {
126 use super::BytesRef;
127
128 #[test]
129 fn should_write_bytes_to_fixed_bytesref() {
130 let mut data1 = vec![0, 0, 0];
132 let mut data2 = vec![0, 0, 0];
133 let (res1, res2) = {
134 let mut bytes1 = BytesRef::Fixed(&mut data1[..]);
135 let mut bytes2 = BytesRef::Fixed(&mut data2[1..2]);
136
137 let res1 = bytes1.write(1, &[1, 1, 1]);
139 let res2 = bytes2.write(3, &[1, 1, 1]);
140 (res1, res2)
141 };
142
143 assert_eq!(&data1, &[0, 1, 1]);
145 assert_eq!(res1, 2);
146
147 assert_eq!(&data2, &[0, 0, 0]);
148 assert_eq!(res2, 0);
149 }
150
151 #[test]
152 fn test_handles_illegal_offsets() {
153 let mut data = vec![0, 0, 0];
155 let res = {
156 let mut bytes = BytesRef::Fixed(&mut data[..]);
157
158 bytes.write(4, &[1])
160 };
161
162 assert_eq!(&data, &[0, 0, 0]);
164 assert_eq!(res, 0);
165 }
166
167 #[test]
168 fn should_write_bytes_to_flexible_bytesref() {
169 let mut data1 = vec![0, 0, 0];
171 let mut data2 = vec![0, 0, 0];
172 let mut data3 = vec![0, 0, 0];
173 let (res1, res2, res3) = {
174 let mut bytes1 = BytesRef::Flexible(&mut data1);
175 let mut bytes2 = BytesRef::Flexible(&mut data2);
176 let mut bytes3 = BytesRef::Flexible(&mut data3);
177
178 let res1 = bytes1.write(1, &[1, 1, 1]);
180 let res2 = bytes2.write(3, &[1, 1, 1]);
181 let res3 = bytes3.write(5, &[1, 1, 1]);
182 (res1, res2, res3)
183 };
184
185 assert_eq!(&data1, &[0, 1, 1, 1]);
187 assert_eq!(res1, 3);
188
189 assert_eq!(&data2, &[0, 0, 0, 1, 1, 1]);
190 assert_eq!(res2, 3);
191
192 assert_eq!(&data3, &[0, 0, 0, 0, 0, 1, 1, 1]);
193 assert_eq!(res3, 5);
194 }
195}