1use std::fmt;
2use std::ops::Deref;
3
4use schemars::JsonSchema;
5use serde::{de, ser, Deserialize, Deserializer, Serialize};
6
7use crate::errors::{StdError, StdResult};
8
9#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
14pub struct Binary(#[schemars(with = "String")] pub Vec<u8>);
15
16impl Binary {
17 pub fn from_base64(encoded: &str) -> StdResult<Self> {
20 let binary = base64::decode(&encoded).map_err(StdError::invalid_base64)?;
21 Ok(Binary(binary))
22 }
23
24 pub fn to_base64(&self) -> String {
27 base64::encode(&self.0)
28 }
29
30 pub fn as_slice(&self) -> &[u8] {
31 self.0.as_slice()
32 }
33
34 pub fn to_array<const LENGTH: usize>(&self) -> StdResult<[u8; LENGTH]> {
62 if self.len() != LENGTH {
63 return Err(StdError::invalid_data_size(LENGTH, self.len()));
64 }
65
66 let mut out: [u8; LENGTH] = [0; LENGTH];
67 out.copy_from_slice(&self.0);
68 Ok(out)
69 }
70}
71
72impl fmt::Display for Binary {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 write!(f, "{}", self.to_base64())
75 }
76}
77
78impl fmt::Debug for Binary {
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 write!(f, "Binary(")?;
83 for byte in self.0.iter() {
84 write!(f, "{:02x}", byte)?;
85 }
86 write!(f, ")")?;
87 Ok(())
88 }
89}
90
91impl From<&[u8]> for Binary {
92 fn from(binary: &[u8]) -> Self {
93 Self(binary.to_vec())
94 }
95}
96
97impl Deref for Binary {
103 type Target = [u8];
104
105 fn deref(&self) -> &Self::Target {
106 self.as_slice()
107 }
108}
109
110impl<const LENGTH: usize> From<&[u8; LENGTH]> for Binary {
112 fn from(source: &[u8; LENGTH]) -> Self {
113 Self(source.to_vec())
114 }
115}
116
117impl<const LENGTH: usize> From<[u8; LENGTH]> for Binary {
119 fn from(source: [u8; LENGTH]) -> Self {
120 Self(source.into())
121 }
122}
123
124impl From<Vec<u8>> for Binary {
125 fn from(vec: Vec<u8>) -> Self {
126 Self(vec)
127 }
128}
129
130impl From<Binary> for Vec<u8> {
131 fn from(original: Binary) -> Vec<u8> {
132 original.0
133 }
134}
135
136impl PartialEq<Vec<u8>> for Binary {
138 fn eq(&self, rhs: &Vec<u8>) -> bool {
139 self.0 == *rhs
141 }
142}
143
144impl PartialEq<Binary> for Vec<u8> {
146 fn eq(&self, rhs: &Binary) -> bool {
147 *self == rhs.0
149 }
150}
151
152impl PartialEq<&[u8]> for Binary {
154 fn eq(&self, rhs: &&[u8]) -> bool {
155 self.as_slice() == *rhs
157 }
158}
159
160impl PartialEq<Binary> for &[u8] {
162 fn eq(&self, rhs: &Binary) -> bool {
163 *self == rhs.as_slice()
165 }
166}
167
168impl Serialize for Binary {
170 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
171 where
172 S: ser::Serializer,
173 {
174 serializer.serialize_str(&self.to_base64())
175 }
176}
177
178impl<'de> Deserialize<'de> for Binary {
180 fn deserialize<D>(deserializer: D) -> Result<Binary, D::Error>
181 where
182 D: Deserializer<'de>,
183 {
184 deserializer.deserialize_str(Base64Visitor)
185 }
186}
187
188struct Base64Visitor;
189
190impl<'de> de::Visitor<'de> for Base64Visitor {
191 type Value = Binary;
192
193 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
194 formatter.write_str("valid base64 encoded string")
195 }
196
197 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
198 where
199 E: de::Error,
200 {
201 match Binary::from_base64(v) {
202 Ok(binary) => Ok(binary),
203 Err(_) => Err(E::custom(format!("invalid base64: {}", v))),
204 }
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211 use crate::errors::StdError;
212 use crate::serde::{from_slice, to_vec};
213 use std::collections::hash_map::DefaultHasher;
214 use std::collections::HashSet;
215 use std::hash::{Hash, Hasher};
216 use std::iter::FromIterator;
217
218 #[test]
219 fn encode_decode() {
220 let binary: &[u8] = b"hello";
221 let encoded = Binary::from(binary).to_base64();
222 assert_eq!(8, encoded.len());
223 let decoded = Binary::from_base64(&encoded).unwrap();
224 assert_eq!(binary, decoded.as_slice());
225 }
226
227 #[test]
228 fn encode_decode_non_ascii() {
229 let binary = vec![12u8, 187, 0, 17, 250, 1];
230 let encoded = Binary(binary.clone()).to_base64();
231 assert_eq!(8, encoded.len());
232 let decoded = Binary::from_base64(&encoded).unwrap();
233 assert_eq!(binary.deref(), decoded.deref());
234 }
235
236 #[test]
237 fn to_array_works() {
238 let binary = Binary::from(&[1, 2, 3]);
240 let array: [u8; 3] = binary.to_array().unwrap();
241 assert_eq!(array, [1, 2, 3]);
242
243 let binary = Binary::from(&[]);
245 let array: [u8; 0] = binary.to_array().unwrap();
246 assert_eq!(array, [] as [u8; 0]);
247
248 let binary = Binary::from(&[1, 2, 3]);
250 let error = binary.to_array::<8>().unwrap_err();
251 match error {
252 StdError::InvalidDataSize {
253 expected, actual, ..
254 } => {
255 assert_eq!(expected, 8);
256 assert_eq!(actual, 3);
257 }
258 err => panic!("Unexpected error: {:?}", err),
259 }
260
261 let binary = Binary::from_base64("t119JOQox4WUQEmO/nyqOZfO+wjJm91YG2sfn4ZglvA=").unwrap();
263 let array: [u8; 32] = binary.to_array().unwrap();
264 assert_eq!(
265 array,
266 [
267 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
268 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
269 0x86, 0x60, 0x96, 0xf0,
270 ]
271 );
272
273 let binary =
275 Binary::from_base64("t119JOQox4WUQEmO/nyqOZfO+wjJm91YG2sfn4ZglvBzyMOwMWq+").unwrap();
276 let array: [u8; 39] = binary.to_array().unwrap();
277 assert_eq!(
278 array,
279 [
280 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
281 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
282 0x86, 0x60, 0x96, 0xf0, 0x73, 0xc8, 0xc3, 0xb0, 0x31, 0x6a, 0xbe,
283 ]
284 );
285 }
286
287 #[test]
288 fn from_valid_string() {
289 let valid_base64 = "cmFuZG9taVo=";
290 let binary = Binary::from_base64(valid_base64).unwrap();
291 assert_eq!(b"randomiZ", binary.as_slice());
292 }
293
294 #[test]
296 fn from_shortened_string() {
297 let short = "cmFuZG9taVo";
298 let long = "cmFuZG9taVo=";
299 let binary = Binary::from_base64(short).unwrap();
300 assert_eq!(b"randomiZ", binary.as_slice());
301 assert_eq!(long, binary.to_base64());
302 }
303
304 #[test]
305 fn from_invalid_string() {
306 let invalid_base64 = "cm%uZG9taVo";
307 let res = Binary::from_base64(invalid_base64);
308 match res.unwrap_err() {
309 StdError::InvalidBase64 { msg, .. } => assert_eq!(msg, "Invalid byte 37, offset 2."),
310 _ => panic!("Unexpected error type"),
311 }
312 }
313
314 #[test]
315 fn from_slice_works() {
316 let original: &[u8] = &[0u8, 187, 61, 11, 250, 0];
317 let binary: Binary = original.into();
318 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
319 }
320
321 #[test]
322 fn from_fixed_length_array_works() {
323 let original = &[];
324 let binary: Binary = original.into();
325 assert_eq!(binary.len(), 0);
326
327 let original = &[0u8];
328 let binary: Binary = original.into();
329 assert_eq!(binary.as_slice(), [0u8]);
330
331 let original = &[0u8, 187, 61, 11, 250, 0];
332 let binary: Binary = original.into();
333 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
334
335 let original = &[
336 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
337 1, 1, 1,
338 ];
339 let binary: Binary = original.into();
340 assert_eq!(
341 binary.as_slice(),
342 [
343 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
344 1, 1, 1, 1,
345 ]
346 );
347 }
348
349 #[test]
350 fn from_owned_fixed_length_array_works() {
351 let original = [];
352 let binary: Binary = original.into();
353 assert_eq!(binary.len(), 0);
354
355 let original = [0u8];
356 let binary: Binary = original.into();
357 assert_eq!(binary.as_slice(), [0u8]);
358
359 let original = [0u8, 187, 61, 11, 250, 0];
360 let binary: Binary = original.into();
361 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
362
363 let original = [
364 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
365 1, 1, 1,
366 ];
367 let binary: Binary = original.into();
368 assert_eq!(
369 binary.as_slice(),
370 [
371 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
372 1, 1, 1, 1,
373 ]
374 );
375 }
376
377 #[test]
378 fn from_literal_works() {
379 let a: Binary = b"".into();
380 assert_eq!(a.len(), 0);
381
382 let a: Binary = b".".into();
383 assert_eq!(a.len(), 1);
384
385 let a: Binary = b"...".into();
386 assert_eq!(a.len(), 3);
387
388 let a: Binary = b"...............................".into();
389 assert_eq!(a.len(), 31);
390
391 let a: Binary = b"................................".into();
392 assert_eq!(a.len(), 32);
393
394 let a: Binary = (b"................................." as &[u8]).into();
396 assert_eq!(a.len(), 33);
397 }
398
399 #[test]
400 fn from_vec_works() {
401 let original = vec![0u8, 187, 61, 11, 250, 0];
402 let original_ptr = original.as_ptr();
403 let binary: Binary = original.into();
404 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
405 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
406 }
407
408 #[test]
409 fn into_vec_works() {
410 let original = Binary(vec![0u8, 187, 61, 11, 250, 0]);
412 let original_ptr = original.0.as_ptr();
413 let vec: Vec<u8> = original.into();
414 assert_eq!(vec.as_slice(), [0u8, 187, 61, 11, 250, 0]);
415 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
416
417 let original = Binary(vec![7u8, 35, 49, 101, 0, 255]);
419 let original_ptr = original.0.as_ptr();
420 let vec = Vec::<u8>::from(original);
421 assert_eq!(vec.as_slice(), [7u8, 35, 49, 101, 0, 255]);
422 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
423 }
424
425 #[test]
426 fn serialization_works() {
427 let binary = Binary(vec![0u8, 187, 61, 11, 250, 0]);
428
429 let json = to_vec(&binary).unwrap();
430 let deserialized: Binary = from_slice(&json).unwrap();
431
432 assert_eq!(binary, deserialized);
433 }
434
435 #[test]
436 fn deserialize_from_valid_string() {
437 let b64_str = "ALs9C/oA";
438 let expected = vec![0u8, 187, 61, 11, 250, 0];
440
441 let serialized = to_vec(&b64_str).unwrap();
442 let deserialized: Binary = from_slice(&serialized).unwrap();
443 assert_eq!(expected, deserialized.as_slice());
444 }
445
446 #[test]
447 fn deserialize_from_invalid_string() {
448 let invalid_str = "**BAD!**";
449 let serialized = to_vec(&invalid_str).unwrap();
450 let res = from_slice::<Binary>(&serialized);
451 assert!(res.is_err());
452 }
453
454 #[test]
455 fn binary_implements_debug() {
456 let binary = Binary(vec![0x07, 0x35, 0xAA, 0xcb, 0x00, 0xff]);
458 assert_eq!(format!("{:?}", binary), "Binary(0735aacb00ff)",);
459
460 let binary = Binary(vec![]);
462 assert_eq!(format!("{:?}", binary), "Binary()",);
463 }
464
465 #[test]
466 fn binary_implements_deref() {
467 let binary = Binary(vec![7u8, 35, 49, 101, 0, 255]);
469 assert_eq!(*binary, [7u8, 35, 49, 101, 0, 255]);
470
471 let binary = Binary(vec![7u8, 35, 49, 101, 0, 255]);
473 assert_eq!(binary.len(), 6);
474 let binary_slice: &[u8] = &binary;
475 assert_eq!(binary_slice, &[7u8, 35, 49, 101, 0, 255]);
476 }
477
478 #[test]
479 fn binary_implements_hash() {
480 let a1 = Binary::from([0, 187, 61, 11, 250, 0]);
481 let mut hasher = DefaultHasher::new();
482 a1.hash(&mut hasher);
483 let a1_hash = hasher.finish();
484
485 let a2 = Binary::from([0, 187, 61, 11, 250, 0]);
486 let mut hasher = DefaultHasher::new();
487 a2.hash(&mut hasher);
488 let a2_hash = hasher.finish();
489
490 let b = Binary::from([16, 21, 33, 0, 255, 9]);
491 let mut hasher = DefaultHasher::new();
492 b.hash(&mut hasher);
493 let b_hash = hasher.finish();
494
495 assert_eq!(a1_hash, a2_hash);
496 assert_ne!(a1_hash, b_hash);
497 }
498
499 #[test]
501 fn binary_can_be_used_in_hash_set() {
502 let a1 = Binary::from([0, 187, 61, 11, 250, 0]);
503 let a2 = Binary::from([0, 187, 61, 11, 250, 0]);
504 let b = Binary::from([16, 21, 33, 0, 255, 9]);
505
506 let mut set = HashSet::new();
507 set.insert(a1.clone());
508 set.insert(a2.clone());
509 set.insert(b.clone());
510 assert_eq!(set.len(), 2);
511
512 let set1 = HashSet::<Binary>::from_iter(vec![b.clone(), a1.clone()]);
513 let set2 = HashSet::from_iter(vec![a1, a2, b]);
514 assert_eq!(set1, set2);
515 }
516
517 #[test]
518 fn binary_implements_partial_eq_with_vector() {
519 let a = Binary(vec![5u8; 3]);
520 let b = vec![5u8; 3];
521 let c = vec![9u8; 3];
522 assert_eq!(a, b);
523 assert_eq!(b, a);
524 assert_ne!(a, c);
525 assert_ne!(c, a);
526 }
527
528 #[test]
529 fn binary_implements_partial_eq_with_slice() {
530 let a = Binary(vec![0xAA, 0xBB]);
531 assert_eq!(a, b"\xAA\xBB" as &[u8]);
532 assert_eq!(b"\xAA\xBB" as &[u8], a);
533 assert_ne!(a, b"\x11\x22" as &[u8]);
534 assert_ne!(b"\x11\x22" as &[u8], a);
535 }
536}