1use alloc::{string::String, vec::Vec};
2use core::fmt;
3use core::ops::Deref;
4
5use serde::{de, ser, Deserialize, Deserializer, Serialize};
6
7use crate::{
8 encoding::{from_base64, to_base64},
9 errors::{StdError, StdResult},
10};
11
12#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, schemars::JsonSchema)]
18pub struct Binary(#[schemars(with = "String")] Vec<u8>);
19
20impl Binary {
21 pub const fn new(data: Vec<u8>) -> Self {
23 Self(data)
24 }
25
26 pub fn from_base64(encoded: &str) -> StdResult<Self> {
29 from_base64(encoded).map(Self::new)
30 }
31
32 pub fn to_base64(&self) -> String {
35 to_base64(&self.0)
36 }
37
38 pub fn as_slice(&self) -> &[u8] {
39 self.0.as_slice()
40 }
41
42 pub fn to_array<const LENGTH: usize>(&self) -> StdResult<[u8; LENGTH]> {
64 if self.len() != LENGTH {
65 return Err(StdError::invalid_data_size(LENGTH, self.len()));
66 }
67
68 let mut out: [u8; LENGTH] = [0; LENGTH];
69 out.copy_from_slice(&self.0);
70 Ok(out)
71 }
72
73 pub fn from_hex(input: &str) -> StdResult<Self> {
74 let binary = hex::decode(input).map_err(StdError::invalid_hex)?;
75 Ok(Self(binary))
76 }
77
78 pub fn to_hex(&self) -> String {
79 hex::encode(&self.0)
80 }
81}
82
83impl fmt::Display for Binary {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 write!(f, "{}", self.to_base64())
86 }
87}
88
89impl fmt::Debug for Binary {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 write!(f, "Binary(")?;
94 for byte in self.0.iter() {
95 write!(f, "{byte:02x}")?;
96 }
97 write!(f, ")")?;
98 Ok(())
99 }
100}
101
102impl Deref for Binary {
108 type Target = [u8];
109
110 fn deref(&self) -> &Self::Target {
111 self.as_slice()
112 }
113}
114
115impl AsRef<[u8]> for Binary {
116 fn as_ref(&self) -> &[u8] {
117 self.as_slice()
118 }
119}
120
121impl From<&[u8]> for Binary {
123 fn from(binary: &[u8]) -> Self {
124 Self(binary.to_vec())
125 }
126}
127
128impl<const LENGTH: usize> From<&[u8; LENGTH]> for Binary {
130 fn from(source: &[u8; LENGTH]) -> Self {
131 Self(source.to_vec())
132 }
133}
134
135impl<const LENGTH: usize> From<[u8; LENGTH]> for Binary {
137 fn from(source: [u8; LENGTH]) -> Self {
138 Self(source.into())
139 }
140}
141
142impl From<Vec<u8>> for Binary {
143 fn from(vec: Vec<u8>) -> Self {
144 Self(vec)
145 }
146}
147
148impl From<Binary> for Vec<u8> {
149 fn from(original: Binary) -> Vec<u8> {
150 original.0
151 }
152}
153
154impl PartialEq<Vec<u8>> for Binary {
156 fn eq(&self, rhs: &Vec<u8>) -> bool {
157 self.0 == *rhs
159 }
160}
161
162impl PartialEq<Binary> for Vec<u8> {
164 fn eq(&self, rhs: &Binary) -> bool {
165 *self == rhs.0
167 }
168}
169
170impl PartialEq<&[u8]> for Binary {
172 fn eq(&self, rhs: &&[u8]) -> bool {
173 self.as_slice() == *rhs
175 }
176}
177
178impl PartialEq<Binary> for &[u8] {
180 fn eq(&self, rhs: &Binary) -> bool {
181 *self == rhs.as_slice()
183 }
184}
185
186impl<const LENGTH: usize> PartialEq<&[u8; LENGTH]> for Binary {
188 fn eq(&self, rhs: &&[u8; LENGTH]) -> bool {
189 self.as_slice() == rhs.as_slice()
190 }
191}
192
193impl<const LENGTH: usize> PartialEq<Binary> for &[u8; LENGTH] {
195 fn eq(&self, rhs: &Binary) -> bool {
196 self.as_slice() == rhs.as_slice()
197 }
198}
199
200impl<const LENGTH: usize> PartialEq<[u8; LENGTH]> for Binary {
202 fn eq(&self, rhs: &[u8; LENGTH]) -> bool {
203 self.as_slice() == rhs.as_slice()
204 }
205}
206
207impl<const LENGTH: usize> PartialEq<Binary> for [u8; LENGTH] {
209 fn eq(&self, rhs: &Binary) -> bool {
210 self.as_slice() == rhs.as_slice()
211 }
212}
213
214impl Serialize for Binary {
216 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
217 where
218 S: ser::Serializer,
219 {
220 if serializer.is_human_readable() {
221 serializer.serialize_str(&self.to_base64())
222 } else {
223 serializer.serialize_bytes(&self.0)
224 }
225 }
226}
227
228impl<'de> Deserialize<'de> for Binary {
230 fn deserialize<D>(deserializer: D) -> Result<Binary, D::Error>
231 where
232 D: Deserializer<'de>,
233 {
234 if deserializer.is_human_readable() {
235 deserializer.deserialize_str(Base64Visitor)
236 } else {
237 deserializer.deserialize_bytes(BytesVisitor)
238 }
239 }
240}
241
242struct Base64Visitor;
243
244impl de::Visitor<'_> for Base64Visitor {
245 type Value = Binary;
246
247 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
248 formatter.write_str("valid base64 encoded string")
249 }
250
251 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
252 where
253 E: de::Error,
254 {
255 match Binary::from_base64(v) {
256 Ok(binary) => Ok(binary),
257 Err(_) => Err(E::custom(format_args!("invalid base64: {v}"))),
258 }
259 }
260}
261
262struct BytesVisitor;
263
264impl de::Visitor<'_> for BytesVisitor {
265 type Value = Binary;
266
267 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
268 formatter.write_str("byte array")
269 }
270
271 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
272 where
273 E: de::Error,
274 {
275 Ok(Binary(v.to_vec()))
276 }
277}
278
279#[cfg(test)]
280mod tests {
281 use super::*;
282 use crate::assert_hash_works;
283 use crate::errors::StdError;
284
285 #[test]
286 fn to_array_works() {
287 let binary = Binary::from(&[1, 2, 3]);
289 let array: [u8; 3] = binary.to_array().unwrap();
290 assert_eq!(array, [1, 2, 3]);
291
292 let binary = Binary::from(&[]);
294 let array: [u8; 0] = binary.to_array().unwrap();
295 assert_eq!(array, [] as [u8; 0]);
296
297 let binary = Binary::from(&[1, 2, 3]);
299 let error = binary.to_array::<8>().unwrap_err();
300 match error {
301 StdError::InvalidDataSize {
302 expected, actual, ..
303 } => {
304 assert_eq!(expected, 8);
305 assert_eq!(actual, 3);
306 }
307 err => panic!("Unexpected error: {err:?}"),
308 }
309
310 let binary = Binary::from_base64("t119JOQox4WUQEmO/nyqOZfO+wjJm91YG2sfn4ZglvA=").unwrap();
312 let array: [u8; 32] = binary.to_array().unwrap();
313 assert_eq!(
314 array,
315 [
316 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
317 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
318 0x86, 0x60, 0x96, 0xf0,
319 ]
320 );
321
322 let binary =
324 Binary::from_base64("t119JOQox4WUQEmO/nyqOZfO+wjJm91YG2sfn4ZglvBzyMOwMWq+").unwrap();
325 let array: [u8; 39] = binary.to_array().unwrap();
326 assert_eq!(
327 array,
328 [
329 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
330 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
331 0x86, 0x60, 0x96, 0xf0, 0x73, 0xc8, 0xc3, 0xb0, 0x31, 0x6a, 0xbe,
332 ]
333 );
334 }
335
336 #[test]
337 fn test_base64_encoding_success() {
338 for (value, encoded, encoded_no_pad) in [
339 (&b""[..], "", ""),
340 (&b"hello"[..], "aGVsbG8=", "aGVsbG8"),
341 (&b"\x0C\xBB\x00\x11\xFA\x01"[..], "DLsAEfoB", "DLsAEfoB"),
342 (&b"rand"[..], "cmFuZA==", "cmFuZA"),
343 (&b"rand"[..], "cmFuZA==", "cmFuZA="),
344 (&b"randomiZ"[..], "cmFuZG9taVo=", "cmFuZG9taVo"),
345 ] {
346 let value = Binary::from(value);
347 assert_eq!(encoded, value.to_base64());
348 assert_eq!(Ok(value.clone()), Binary::from_base64(encoded));
349 assert_eq!(Ok(value.clone()), Binary::from_base64(encoded_no_pad));
350 }
351 }
352
353 #[test]
354 fn test_base64_encoding_error() {
355 for (invalid_base64, want) in [
356 ("cm%uZG9taVo", "Invalid symbol 37, offset 2."),
357 ("cmFuZ", "Invalid input length: 5"),
358 ] {
359 match Binary::from_base64(invalid_base64) {
360 Err(StdError::InvalidBase64 { msg, .. }) => assert_eq!(want, msg),
361 result => panic!("Unexpected result: {result:?}"),
362 }
363 }
364 }
365
366 #[test]
367 fn from_slice_works() {
368 let original: &[u8] = &[0u8, 187, 61, 11, 250, 0];
369 let binary: Binary = original.into();
370 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
371 }
372
373 #[test]
374 fn from_fixed_length_array_works() {
375 let original = &[];
376 let binary: Binary = original.into();
377 assert_eq!(binary.len(), 0);
378
379 let original = &[0u8];
380 let binary: Binary = original.into();
381 assert_eq!(binary.as_slice(), [0u8]);
382
383 let original = &[0u8, 187, 61, 11, 250, 0];
384 let binary: Binary = original.into();
385 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
386
387 let original = &[
388 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,
389 1, 1, 1,
390 ];
391 let binary: Binary = original.into();
392 assert_eq!(
393 binary.as_slice(),
394 [
395 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,
396 1, 1, 1, 1,
397 ]
398 );
399 }
400
401 #[test]
402 fn from_owned_fixed_length_array_works() {
403 let original = [];
404 let binary: Binary = original.into();
405 assert_eq!(binary.len(), 0);
406
407 let original = [0u8];
408 let binary: Binary = original.into();
409 assert_eq!(binary.as_slice(), [0u8]);
410
411 let original = [0u8, 187, 61, 11, 250, 0];
412 let binary: Binary = original.into();
413 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
414
415 let original = [
416 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,
417 1, 1, 1,
418 ];
419 let binary: Binary = original.into();
420 assert_eq!(
421 binary.as_slice(),
422 [
423 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,
424 1, 1, 1, 1,
425 ]
426 );
427 }
428
429 #[test]
430 fn from_literal_works() {
431 let a: Binary = b"".into();
432 assert_eq!(a.len(), 0);
433
434 let a: Binary = b".".into();
435 assert_eq!(a.len(), 1);
436
437 let a: Binary = b"...".into();
438 assert_eq!(a.len(), 3);
439
440 let a: Binary = b"...............................".into();
441 assert_eq!(a.len(), 31);
442
443 let a: Binary = b"................................".into();
444 assert_eq!(a.len(), 32);
445
446 let a: Binary = b".................................".into();
447 assert_eq!(a.len(), 33);
448 }
449
450 #[test]
451 fn from_vec_works() {
452 let original = vec![0u8, 187, 61, 11, 250, 0];
453 let original_ptr = original.as_ptr();
454 let binary: Binary = original.into();
455 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
456 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
457 }
458
459 #[test]
460 fn into_vec_works() {
461 let original = Binary(vec![0u8, 187, 61, 11, 250, 0]);
463 let original_ptr = original.0.as_ptr();
464 let vec: Vec<u8> = original.into();
465 assert_eq!(vec.as_slice(), [0u8, 187, 61, 11, 250, 0]);
466 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
467
468 let original = Binary(vec![7u8, 35, 49, 101, 0, 255]);
470 let original_ptr = original.0.as_ptr();
471 let vec = Vec::<u8>::from(original);
472 assert_eq!(vec.as_slice(), [7u8, 35, 49, 101, 0, 255]);
473 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
474 }
475
476 #[test]
477 fn json_serialization_works() {
478 let binary = Binary(vec![0u8, 187, 61, 11, 250, 0]);
479
480 let json = serde_json::to_vec(&binary).unwrap();
481 let deserialized: Binary = serde_json::from_slice(&json).unwrap();
482
483 assert_eq!(binary, deserialized);
484 }
485
486 #[test]
487 fn json_deserialize_from_valid_string() {
488 let b64_str = "ALs9C/oA";
489 let expected = vec![0u8, 187, 61, 11, 250, 0];
491
492 let serialized = serde_json::to_vec(&b64_str).unwrap();
493 let deserialized: Binary = serde_json::from_slice(&serialized).unwrap();
494 assert_eq!(expected, deserialized.as_slice());
495 }
496
497 #[test]
498 fn json_deserialize_from_invalid_string() {
499 let invalid_str = "**BAD!**";
500 let serialized = serde_json::to_vec(&invalid_str).unwrap();
501 let res = serde_json::from_slice::<Binary>(&serialized);
502 assert!(res.is_err());
503 }
504
505 #[test]
506 fn msgpack_serialization_works() {
507 let data = Binary(vec![0u8, 187, 61, 11, 250, 0]);
508 let expected = [196, 6, 0, 187, 61, 11, 250, 0];
510
511 assert_eq!(rmp_serde::to_vec(&data).unwrap(), expected);
512 }
513
514 #[test]
515 fn msgpack_deserialize_from_valid_data() {
516 let serialized = vec![196, 6, 0, 187, 61, 11, 250, 0];
518 let expected = vec![0u8, 187, 61, 11, 250, 0];
519
520 let deserialized: Binary = rmp_serde::from_slice(&serialized).unwrap();
521 assert_eq!(expected, deserialized.as_slice());
522 }
523
524 #[test]
525 fn msgpack_deserialize_from_invalid_data() {
526 let invalid_data = vec![0, 1, 2, 3, 4, 5];
527 let res = rmp_serde::from_slice::<Binary>(&invalid_data);
528 assert!(res.is_err());
529 }
530
531 #[test]
532 fn binary_implements_debug() {
533 let binary = Binary(vec![0x07, 0x35, 0xAA, 0xcb, 0x00, 0xff]);
535 assert_eq!(format!("{binary:?}"), "Binary(0735aacb00ff)",);
536
537 let binary = Binary(vec![]);
539 assert_eq!(format!("{binary:?}"), "Binary()",);
540 }
541
542 #[test]
543 fn binary_implements_deref() {
544 let binary = Binary(vec![7u8, 35, 49, 101, 0, 255]);
546 assert_eq!(*binary, [7u8, 35, 49, 101, 0, 255]);
547
548 let binary = Binary(vec![7u8, 35, 49, 101, 0, 255]);
550 assert_eq!(binary.len(), 6);
551 let binary_slice: &[u8] = &binary;
552 assert_eq!(binary_slice, &[7u8, 35, 49, 101, 0, 255]);
553 }
554
555 #[test]
556 fn binary_implements_as_ref() {
557 let want = &[7u8, 35, 49, 101, 0, 255];
558 let data = Binary(want.to_vec());
559 assert_eq!(want, AsRef::<[u8]>::as_ref(&data));
560 assert_eq!(want, AsRef::<[u8]>::as_ref(&&data));
561 }
562
563 #[test]
566 fn binary_implements_hash_eq() {
567 let a = Binary::from([0, 187, 61, 11, 250, 0]);
568 let b = Binary::from([16, 21, 33, 0, 255, 9]);
569 assert_hash_works!(a, b);
570 }
571
572 #[test]
573 fn binary_implements_partial_eq_with_vector() {
574 let a = Binary(vec![5u8; 3]);
575 let b = vec![5u8; 3];
576 let c = vec![9u8; 3];
577 assert_eq!(a, b);
578 assert_eq!(b, a);
579 assert_ne!(a, c);
580 assert_ne!(c, a);
581 }
582
583 #[test]
584 fn binary_implements_partial_eq_with_slice_and_array() {
585 let a = Binary(vec![0xAA, 0xBB]);
586
587 assert_eq!(a, b"\xAA\xBB" as &[u8]);
589 assert_eq!(b"\xAA\xBB" as &[u8], a);
590 assert_ne!(a, b"\x11\x22" as &[u8]);
591 assert_ne!(b"\x11\x22" as &[u8], a);
592
593 assert_eq!(a, b"\xAA\xBB");
595 assert_eq!(b"\xAA\xBB", a);
596 assert_ne!(a, b"\x11\x22");
597 assert_ne!(b"\x11\x22", a);
598
599 assert_eq!(a, [0xAA, 0xBB]);
601 assert_eq!([0xAA, 0xBB], a);
602 assert_ne!(a, [0x11, 0x22]);
603 assert_ne!([0x11, 0x22], a);
604 }
605
606 #[test]
607 fn hex_encoding_works() {
608 let hash = "722c8c993fd75a7627d69ed941344fe2a1423a3e75efd3e6778a142884227104";
609 let parsed = Binary::from_hex(hash).unwrap();
610 assert_eq!(parsed.to_hex(), hash);
611
612 let odd_num_of_digits = "722c8c993fd75a7627d69ed941344fe2a1423a3e75efd3e6778a142884227";
614 assert!(Binary::from_hex(odd_num_of_digits).is_err());
615 let invalid_char = "722c8c993fd75a7627d69ed941344fe2a1423a3e75efd3e6778a1428842271g4";
616 assert!(Binary::from_hex(invalid_char).is_err());
617 let hex_prefix_unexpected =
618 "0x722c8c993fd75a7627d69ed941344fe2a1423a3e75efd3e6778a142884227104";
619 assert!(Binary::from_hex(hex_prefix_unexpected).is_err());
620 }
621}