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