1#![deny(missing_docs)]
27
28extern crate base64;
29extern crate serde;
30
31use std::borrow::{Borrow, BorrowMut};
32use std::fmt::{self, Display};
33use std::hash::{Hash, Hasher};
34use std::io::{self, Write};
35use std::iter::{Extend, FromIterator, IntoIterator};
36use std::marker::PhantomData;
37use std::ops::{Deref, DerefMut};
38use std::slice::{Iter, IterMut};
39use std::str::FromStr;
40use std::vec::IntoIter;
41
42pub trait Config: Send + Sync {
44 const CONFIG: base64::Config;
46}
47
48macro_rules! impl_configs {
49 ($($(#[$($attrs:tt)*])* $name:ident: $config:ident,)*) => {
50 $(
51 $(#[$($attrs)*])*
52 pub enum $name {}
53
54 impl Config for $name {
55 const CONFIG: base64::Config = base64::$config;
56 }
57 )*
58 }
59}
60
61impl_configs! {
62 Crypt: CRYPT,
64
65 Standard: STANDARD,
67
68 StandardNoPad: STANDARD_NO_PAD,
70
71 UrlSafe: URL_SAFE,
73
74 UrlSafeNoPad: URL_SAFE_NO_PAD,
76}
77
78pub struct Blob<C: Config = Standard> {
84 data: Vec<u8>,
85 _config: PhantomData<C>,
86}
87
88impl<C: Config> Default for Blob<C> {
89 #[inline]
90 fn default() -> Self {
91 Blob {
92 data: Vec::new(),
93 _config: PhantomData,
94 }
95 }
96}
97
98impl<C: Config> Blob<C> {
99 #[inline]
101 pub fn new() -> Blob<C> {
102 Blob::default()
103 }
104
105 #[inline]
107 pub fn from_vec(vec: Vec<u8>) -> Blob<C> {
108 Blob {
109 data: vec,
110 _config: PhantomData,
111 }
112 }
113
114 #[inline]
116 pub fn with_capacity(capacity: usize) -> Blob<C> {
117 Blob::from_vec(Vec::with_capacity(capacity))
118 }
119
120 #[inline]
122 pub fn capacity(&self) -> usize {
123 self.data.capacity()
124 }
125
126 #[inline]
128 pub fn reserve(&mut self, additional: usize) {
129 self.data.reserve(additional)
130 }
131
132 #[inline(always)]
134 pub fn with_config<E: Config>(self) -> Blob<E> {
135 Blob {
136 data: self.data,
137 _config: PhantomData,
138 }
139 }
140
141 #[inline]
143 pub fn encode_base64(&self) -> String {
144 base64::encode_config(&self.data, C::CONFIG)
145 }
146
147 pub fn encode_to<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
149 let mut encoder = base64::write::EncoderWriter::new(&mut writer, C::CONFIG);
150
151 encoder.write_all(&self.data)
152 }
153
154 pub fn decode_base64<T>(encoded: T) -> Result<Blob<C>, base64::DecodeError>
156 where
157 T: AsRef<[u8]>,
158 {
159 base64::decode_config(encoded.as_ref(), C::CONFIG).map(Blob::from_vec)
161 }
162
163 #[inline]
165 pub fn append_base64<T>(&mut self, encoded: T) -> Result<(), base64::DecodeError>
166 where
167 T: AsRef<[u8]>,
168 {
169 base64::decode_config_buf(encoded.as_ref(), C::CONFIG, &mut self.data)
171 }
172
173 #[inline]
175 pub fn into_vec(self) -> Vec<u8> {
176 self.data
177 }
178}
179
180impl<C: Config> FromStr for Blob<C> {
181 type Err = base64::DecodeError;
182
183 #[inline]
184 fn from_str(s: &str) -> Result<Self, Self::Err> {
185 Blob::decode_base64(s)
186 }
187}
188
189impl<C: Config> Clone for Blob<C> {
190 #[inline]
191 fn clone(&self) -> Blob<C> {
192 Blob {
193 data: self.data.clone(),
194 _config: PhantomData,
195 }
196 }
197}
198
199impl<C: Config> fmt::Debug for Blob<C> {
200 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
201 f.debug_tuple("Blob").field(&self.data).finish()
202 }
203}
204
205impl<C: Config> Display for Blob<C> {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 base64::display::Base64Display::with_config(&self.data, C::CONFIG).fmt(f)
208 }
209}
210
211impl<C: Config> Hash for Blob<C> {
212 #[inline]
213 fn hash<H: Hasher>(&self, state: &mut H) {
214 self.data.hash(state);
215 }
216}
217
218impl<C: Config> Write for Blob<C> {
219 #[inline(always)]
220 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
221 self.data.write(buf)
222 }
223
224 #[inline(always)]
225 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
226 self.data.write_all(buf)
227 }
228
229 #[inline(always)]
230 fn flush(&mut self) -> io::Result<()> {
231 self.data.flush()
232 }
233}
234
235impl<C: Config> FromIterator<u8> for Blob<C> {
236 fn from_iter<I>(iter: I) -> Blob<C>
237 where
238 I: IntoIterator<Item = u8>,
239 {
240 Blob::from_vec(Vec::from_iter(iter))
241 }
242}
243
244impl<C: Config> Extend<u8> for Blob<C> {
245 #[inline]
246 fn extend<T>(&mut self, iter: T)
247 where
248 T: IntoIterator<Item = u8>,
249 {
250 self.data.extend(iter)
251 }
252}
253
254impl<'a, C: Config> Extend<&'a u8> for Blob<C> {
255 #[inline]
256 fn extend<T>(&mut self, iter: T)
257 where
258 T: IntoIterator<Item = &'a u8>,
259 {
260 self.data.extend(iter)
261 }
262}
263
264impl<C: Config> IntoIterator for Blob<C> {
265 type Item = u8;
266 type IntoIter = IntoIter<u8>;
267
268 #[inline]
269 fn into_iter(self) -> Self::IntoIter {
270 self.data.into_iter()
271 }
272}
273
274impl<'a, C: Config> IntoIterator for &'a Blob<C> {
275 type Item = &'a u8;
276 type IntoIter = Iter<'a, u8>;
277
278 #[inline]
279 fn into_iter(self) -> Self::IntoIter {
280 self.data.iter()
281 }
282}
283
284impl<'a, C: Config> IntoIterator for &'a mut Blob<C> {
285 type Item = &'a mut u8;
286 type IntoIter = IterMut<'a, u8>;
287
288 #[inline]
289 fn into_iter(self) -> Self::IntoIter {
290 self.data.iter_mut()
291 }
292}
293
294impl<C: Config> Deref for Blob<C> {
295 type Target = [u8];
296
297 #[inline(always)]
298 fn deref(&self) -> &Self::Target {
299 &self.data
300 }
301}
302
303impl<C: Config> DerefMut for Blob<C> {
304 #[inline(always)]
305 fn deref_mut(&mut self) -> &mut Self::Target {
306 &mut self.data
307 }
308}
309
310impl<T, C: Config> From<T> for Blob<C>
311where
312 T: Into<Vec<u8>>,
313{
314 #[inline(always)]
315 fn from(value: T) -> Blob<C> {
316 Blob::from_vec(value.into())
317 }
318}
319
320impl<C: Config> PartialEq<Self> for Blob<C> {
321 #[inline(always)]
322 fn eq(&self, other: &Self) -> bool {
323 self.data.eq(&other.data)
324 }
325}
326
327impl<C: Config> Eq for Blob<C> {}
328
329impl<T, C: Config> PartialEq<T> for Blob<C>
330where
331 Vec<u8>: PartialEq<T>,
332{
333 #[inline(always)]
334 fn eq(&self, other: &T) -> bool {
335 self.data == *other
336 }
337}
338
339impl<C: Config> AsRef<[u8]> for Blob<C> {
340 #[inline(always)]
341 fn as_ref(&self) -> &[u8] {
342 &self.data
343 }
344}
345
346impl<C: Config> AsRef<Vec<u8>> for Blob<C> {
347 #[inline(always)]
348 fn as_ref(&self) -> &Vec<u8> {
349 &self.data
350 }
351}
352
353impl<C: Config> AsMut<[u8]> for Blob<C> {
354 #[inline(always)]
355 fn as_mut(&mut self) -> &mut [u8] {
356 &mut self.data
357 }
358}
359
360impl<C: Config> AsMut<Vec<u8>> for Blob<C> {
361 #[inline(always)]
362 fn as_mut(&mut self) -> &mut Vec<u8> {
363 &mut self.data
364 }
365}
366
367impl<C: Config> Borrow<Vec<u8>> for Blob<C> {
368 fn borrow(&self) -> &Vec<u8> {
369 &self.data
370 }
371}
372
373impl<C: Config> BorrowMut<Vec<u8>> for Blob<C> {
374 fn borrow_mut(&mut self) -> &mut Vec<u8> {
375 &mut self.data
376 }
377}
378
379impl<C: Config> serde::Serialize for Blob<C> {
380 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
381 where
382 S: serde::Serializer,
383 {
384 let encoded = self.encode_base64();
385
386 serializer.serialize_str(encoded.as_str())
387 }
388}
389
390impl<'de, C: Config> serde::Deserialize<'de> for Blob<C> {
391 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
392 where
393 D: serde::Deserializer<'de>,
394 {
395 struct BlobVisitor<C: Config>(PhantomData<C>);
396
397 impl<'de, C: Config> serde::de::Visitor<'de> for BlobVisitor<C> {
398 type Value = Blob<C>;
399
400 fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
401 f.write_str("base64 encoded string or byte sequence")
402 }
403
404 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
405 where
406 E: serde::de::Error,
407 {
408 FromStr::from_str(value).map_err(E::custom)
409 }
410
411 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
412 where
413 E: serde::de::Error,
414 {
415 Ok(Blob::from_vec(value.to_owned()))
416 }
417
418 fn visit_byte_buf<E>(self, value: Vec<u8>) -> Result<Self::Value, E>
419 where
420 E: serde::de::Error,
421 {
422 Ok(Blob::from_vec(value))
423 }
424
425 fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
426 where
427 V: serde::de::SeqAccess<'de>,
428 {
429 let mut bytes = Vec::with_capacity(visitor.size_hint().unwrap_or(0).min(4096));
431
432 while let Some(byte) = visitor.next_element()? {
433 bytes.push(byte);
434 }
435
436 Ok(Blob::from_vec(bytes))
437 }
438 }
439
440 deserializer.deserialize_any(BlobVisitor(PhantomData))
441 }
442}