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_hex, to_hex},
9 Binary, StdError, StdResult,
10};
11
12#[derive(
18 Clone,
19 Default,
20 PartialEq,
21 Eq,
22 Hash,
23 PartialOrd,
24 Ord,
25 schemars::JsonSchema,
26 cw_schema::Schemaifier,
27)]
28#[schemaifier(type = cw_schema::NodeType::HexBinary)]
29pub struct HexBinary(#[schemars(with = "String")] Vec<u8>);
30
31impl HexBinary {
32 pub fn from_hex(input: &str) -> StdResult<Self> {
33 from_hex(input).map(Self)
34 }
35
36 pub fn to_hex(&self) -> String {
37 to_hex(&self.0)
38 }
39
40 pub fn as_slice(&self) -> &[u8] {
41 self.0.as_slice()
42 }
43
44 pub fn to_array<const LENGTH: usize>(&self) -> StdResult<[u8; LENGTH]> {
66 if self.len() != LENGTH {
67 return Err(StdError::msg(format_args!(
68 "invalid length. expected {LENGTH}, got {}",
69 self.len()
70 )));
71 }
72
73 let mut out: [u8; LENGTH] = [0; LENGTH];
74 out.copy_from_slice(&self.0);
75 Ok(out)
76 }
77}
78
79impl fmt::Display for HexBinary {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 write!(f, "{}", self.to_hex())
82 }
83}
84
85impl fmt::Debug for HexBinary {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 write!(f, "HexBinary(")?;
90 for byte in self.0.iter() {
91 write!(f, "{byte:02x}")?;
92 }
93 write!(f, ")")?;
94 Ok(())
95 }
96}
97
98impl Deref for HexBinary {
104 type Target = [u8];
105
106 fn deref(&self) -> &Self::Target {
107 self.as_slice()
108 }
109}
110
111impl AsRef<[u8]> for HexBinary {
112 fn as_ref(&self) -> &[u8] {
113 self.as_slice()
114 }
115}
116
117impl From<&[u8]> for HexBinary {
119 fn from(binary: &[u8]) -> Self {
120 Self(binary.to_vec())
121 }
122}
123
124impl<const LENGTH: usize> From<&[u8; LENGTH]> for HexBinary {
126 fn from(source: &[u8; LENGTH]) -> Self {
127 Self(source.to_vec())
128 }
129}
130
131impl<const LENGTH: usize> From<[u8; LENGTH]> for HexBinary {
133 fn from(source: [u8; LENGTH]) -> Self {
134 Self(source.into())
135 }
136}
137
138impl From<Vec<u8>> for HexBinary {
139 fn from(vec: Vec<u8>) -> Self {
140 Self(vec)
141 }
142}
143
144impl From<HexBinary> for Vec<u8> {
145 fn from(original: HexBinary) -> Vec<u8> {
146 original.0
147 }
148}
149
150impl From<Binary> for HexBinary {
151 fn from(original: Binary) -> Self {
152 Self(original.into())
153 }
154}
155
156impl From<HexBinary> for Binary {
157 fn from(original: HexBinary) -> Binary {
158 Binary::from(original.0)
159 }
160}
161
162impl PartialEq<Vec<u8>> for HexBinary {
164 fn eq(&self, rhs: &Vec<u8>) -> bool {
165 self.0 == *rhs
167 }
168}
169
170impl PartialEq<HexBinary> for Vec<u8> {
172 fn eq(&self, rhs: &HexBinary) -> bool {
173 *self == rhs.0
175 }
176}
177
178impl PartialEq<&[u8]> for HexBinary {
180 fn eq(&self, rhs: &&[u8]) -> bool {
181 self.as_slice() == *rhs
183 }
184}
185
186impl PartialEq<HexBinary> for &[u8] {
188 fn eq(&self, rhs: &HexBinary) -> bool {
189 *self == rhs.as_slice()
191 }
192}
193
194impl<const LENGTH: usize> PartialEq<[u8; LENGTH]> for HexBinary {
196 fn eq(&self, rhs: &[u8; LENGTH]) -> bool {
197 self.as_slice() == rhs.as_slice()
198 }
199}
200
201impl<const LENGTH: usize> PartialEq<HexBinary> for [u8; LENGTH] {
203 fn eq(&self, rhs: &HexBinary) -> bool {
204 self.as_slice() == rhs.as_slice()
205 }
206}
207
208impl<const LENGTH: usize> PartialEq<&[u8; LENGTH]> for HexBinary {
210 fn eq(&self, rhs: &&[u8; LENGTH]) -> bool {
211 self.as_slice() == rhs.as_slice()
212 }
213}
214
215impl<const LENGTH: usize> PartialEq<HexBinary> for &[u8; LENGTH] {
217 fn eq(&self, rhs: &HexBinary) -> bool {
218 self.as_slice() == rhs.as_slice()
219 }
220}
221
222impl Serialize for HexBinary {
224 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
225 where
226 S: ser::Serializer,
227 {
228 if serializer.is_human_readable() {
229 serializer.serialize_str(&self.to_hex())
230 } else {
231 serializer.serialize_bytes(&self.0)
232 }
233 }
234}
235
236impl<'de> Deserialize<'de> for HexBinary {
238 fn deserialize<D>(deserializer: D) -> Result<HexBinary, D::Error>
239 where
240 D: Deserializer<'de>,
241 {
242 if deserializer.is_human_readable() {
243 deserializer.deserialize_str(HexVisitor)
244 } else {
245 deserializer.deserialize_bytes(BytesVisitor)
246 }
247 }
248}
249
250struct HexVisitor;
251
252impl de::Visitor<'_> for HexVisitor {
253 type Value = HexBinary;
254
255 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
256 formatter.write_str("valid hex encoded string")
257 }
258
259 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
260 where
261 E: de::Error,
262 {
263 match HexBinary::from_hex(v) {
264 Ok(data) => Ok(data),
265 Err(_) => Err(E::custom(format!("invalid hex: {v}"))),
266 }
267 }
268}
269
270struct BytesVisitor;
271
272impl de::Visitor<'_> for BytesVisitor {
273 type Value = HexBinary;
274
275 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
276 formatter.write_str("byte array")
277 }
278
279 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
280 where
281 E: de::Error,
282 {
283 Ok(HexBinary(v.to_vec()))
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use super::*;
290
291 use crate::{assert_hash_works, errors::ErrorKind};
292
293 #[test]
294 fn from_hex_works() {
295 let data = HexBinary::from_hex("").unwrap();
296 assert_eq!(data, b"");
297 let data = HexBinary::from_hex("61").unwrap();
298 assert_eq!(data, b"a");
299 let data = HexBinary::from_hex("00").unwrap();
300 assert_eq!(data, b"\0");
301
302 let data = HexBinary::from_hex("68656c6c6f").unwrap();
303 assert_eq!(data, b"hello");
304 let data = HexBinary::from_hex("68656C6C6F").unwrap();
305 assert_eq!(data, b"hello");
306 let data = HexBinary::from_hex("72616e646f6d695a").unwrap();
307 assert_eq!(data.as_slice(), b"randomiZ");
308
309 assert!(HexBinary::from_hex("123")
311 .unwrap_err()
312 .to_string()
313 .ends_with("Odd number of digits"));
314 assert!(HexBinary::from_hex("efgh")
316 .unwrap_err()
317 .to_string()
318 .ends_with("Invalid character 'g' at position 2"));
319 assert!(HexBinary::from_hex("0xaa")
321 .unwrap_err()
322 .to_string()
323 .ends_with("Invalid character 'x' at position 1"));
324 assert!(matches!(
326 HexBinary::from_hex("aa ").unwrap_err().kind(),
327 ErrorKind::Encoding,
328 ));
329 assert!(matches!(
330 HexBinary::from_hex(" aa").unwrap_err().kind(),
331 ErrorKind::Encoding,
332 ));
333 assert!(matches!(
334 HexBinary::from_hex("a a").unwrap_err().kind(),
335 ErrorKind::Encoding,
336 ));
337 assert!(matches!(
338 HexBinary::from_hex(" aa ").unwrap_err().kind(),
339 ErrorKind::Encoding,
340 ));
341 }
342
343 #[test]
344 fn to_hex_works() {
345 let binary: &[u8] = b"";
346 let encoded = HexBinary::from(binary).to_hex();
347 assert_eq!(encoded, "");
348
349 let binary: &[u8] = b"hello";
350 let encoded = HexBinary::from(binary).to_hex();
351 assert_eq!(encoded, "68656c6c6f");
352
353 let binary = vec![12u8, 187, 0, 17, 250, 1];
354 let encoded = HexBinary(binary).to_hex();
355 assert_eq!(encoded, "0cbb0011fa01");
356 }
357
358 #[test]
359 fn to_array_works() {
360 let binary = HexBinary::from(&[1, 2, 3]);
362 let array: [u8; 3] = binary.to_array().unwrap();
363 assert_eq!(array, [1, 2, 3]);
364
365 let binary = HexBinary::from(&[]);
367 let array: [u8; 0] = binary.to_array().unwrap();
368 assert_eq!(array, [] as [u8; 0]);
369
370 let binary = HexBinary::from(&[1, 2, 3]);
372 let error = binary.to_array::<8>().unwrap_err();
373 assert!(error
374 .to_string()
375 .ends_with("invalid length. expected 8, got 3"));
376
377 let binary =
379 HexBinary::from_hex("b75d7d24e428c7859440498efe7caa3997cefb08c99bdd581b6b1f9f866096f0")
380 .unwrap();
381 let array: [u8; 32] = binary.to_array().unwrap();
382 assert_eq!(
383 array,
384 [
385 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
386 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
387 0x86, 0x60, 0x96, 0xf0,
388 ]
389 );
390
391 let binary = HexBinary::from_hex(
393 "b75d7d24e428c7859440498efe7caa3997cefb08c99bdd581b6b1f9f866096f073c8c3b0316abe",
394 )
395 .unwrap();
396 let array: [u8; 39] = binary.to_array().unwrap();
397 assert_eq!(
398 array,
399 [
400 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
401 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
402 0x86, 0x60, 0x96, 0xf0, 0x73, 0xc8, 0xc3, 0xb0, 0x31, 0x6a, 0xbe,
403 ]
404 );
405 }
406
407 #[test]
408 fn from_json_works() {
409 let original: &[u8] = &[0u8, 187, 61, 11, 250, 0];
410 let binary: HexBinary = original.into();
411 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
412 }
413
414 #[test]
415 fn from_fixed_length_array_works() {
416 let original = &[];
417 let binary: HexBinary = original.into();
418 assert_eq!(binary.len(), 0);
419
420 let original = &[0u8];
421 let binary: HexBinary = original.into();
422 assert_eq!(binary.as_slice(), [0u8]);
423
424 let original = &[0u8, 187, 61, 11, 250, 0];
425 let binary: HexBinary = original.into();
426 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
427
428 let original = &[
429 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,
430 1, 1, 1,
431 ];
432 let binary: HexBinary = original.into();
433 assert_eq!(
434 binary.as_slice(),
435 [
436 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,
437 1, 1, 1, 1,
438 ]
439 );
440 }
441
442 #[test]
443 fn from_owned_fixed_length_array_works() {
444 let original = [];
445 let binary: HexBinary = original.into();
446 assert_eq!(binary.len(), 0);
447
448 let original = [0u8];
449 let binary: HexBinary = original.into();
450 assert_eq!(binary.as_slice(), [0u8]);
451
452 let original = [0u8, 187, 61, 11, 250, 0];
453 let binary: HexBinary = original.into();
454 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
455
456 let original = [
457 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,
458 1, 1, 1,
459 ];
460 let binary: HexBinary = original.into();
461 assert_eq!(
462 binary.as_slice(),
463 [
464 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,
465 1, 1, 1, 1,
466 ]
467 );
468 }
469
470 #[test]
471 fn from_literal_works() {
472 let a: HexBinary = b"".into();
473 assert_eq!(a.len(), 0);
474
475 let a: HexBinary = b".".into();
476 assert_eq!(a.len(), 1);
477
478 let a: HexBinary = b"...".into();
479 assert_eq!(a.len(), 3);
480
481 let a: HexBinary = b"...............................".into();
482 assert_eq!(a.len(), 31);
483
484 let a: HexBinary = b"................................".into();
485 assert_eq!(a.len(), 32);
486
487 let a: HexBinary = (b".................................").into();
488 assert_eq!(a.len(), 33);
489 }
490
491 #[test]
492 fn from_vec_works() {
493 let original = vec![0u8, 187, 61, 11, 250, 0];
494 let original_ptr = original.as_ptr();
495 let binary: HexBinary = original.into();
496 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
497 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
498 }
499
500 #[test]
501 fn into_vec_works() {
502 let original = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
504 let original_ptr = original.0.as_ptr();
505 let vec: Vec<u8> = original.into();
506 assert_eq!(vec.as_slice(), [0u8, 187, 61, 11, 250, 0]);
507 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
508
509 let original = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
511 let original_ptr = original.0.as_ptr();
512 let vec = Vec::<u8>::from(original);
513 assert_eq!(vec.as_slice(), [7u8, 35, 49, 101, 0, 255]);
514 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
515 }
516
517 #[test]
518 fn from_binary_works() {
519 let original = Binary::from([0u8, 187, 61, 11, 250, 0]);
520 let original_ptr = original.as_ptr();
521 let binary: HexBinary = original.into();
522 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
523 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
524 }
525
526 #[test]
527 fn into_binary_works() {
528 let original = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
530 let original_ptr = original.0.as_ptr();
531 let bin: Binary = original.into();
532 assert_eq!(bin.as_slice(), [0u8, 187, 61, 11, 250, 0]);
533 assert_eq!(bin.as_ptr(), original_ptr, "vector must not be copied");
534
535 let original = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
537 let original_ptr = original.0.as_ptr();
538 let bin = Binary::from(original);
539 assert_eq!(bin.as_slice(), [7u8, 35, 49, 101, 0, 255]);
540 assert_eq!(bin.as_ptr(), original_ptr, "vector must not be copied");
541 }
542
543 #[test]
544 fn serialization_works() {
545 let binary = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
546
547 let json = serde_json::to_vec(&binary).unwrap();
548 let deserialized: HexBinary = serde_json::from_slice(&json).unwrap();
549
550 assert_eq!(binary, deserialized);
551 }
552
553 #[test]
554 fn deserialize_from_valid_string() {
555 let hex = "00bb3d0bfa00";
556 let expected = vec![0u8, 187, 61, 11, 250, 0];
558
559 let serialized = serde_json::to_vec(&hex).unwrap();
560 let deserialized: HexBinary = serde_json::from_slice(&serialized).unwrap();
561 assert_eq!(expected, deserialized.as_slice());
562 }
563
564 #[test]
565 fn deserialize_from_invalid_string() {
566 let invalid_str = "**BAD!**";
567 let serialized = serde_json::to_vec(&invalid_str).unwrap();
568 let res = serde_json::from_slice::<HexBinary>(&serialized);
569 assert!(res.is_err());
570 }
571
572 #[test]
573 fn msgpack_serialization_works() {
574 let data = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
575 let expected = [196, 6, 0, 187, 61, 11, 250, 0];
577
578 assert_eq!(rmp_serde::to_vec(&data).unwrap(), expected);
579 }
580
581 #[test]
582 fn msgpack_deserialize_from_valid_data() {
583 let serialized = vec![196, 6, 0, 187, 61, 11, 250, 0];
585 let expected = vec![0u8, 187, 61, 11, 250, 0];
586
587 let deserialized: HexBinary = rmp_serde::from_slice(&serialized).unwrap();
588 assert_eq!(expected, deserialized.as_slice());
589 }
590
591 #[test]
592 fn msgpack_deserialize_from_invalid_data() {
593 let invalid_data = vec![0, 1, 2, 3, 4, 5];
594 let res = rmp_serde::from_slice::<HexBinary>(&invalid_data);
595 assert!(res.is_err());
596 }
597
598 #[test]
599 fn hex_binary_implements_debug() {
600 let data = HexBinary(vec![0x07, 0x35, 0xAA, 0xcb, 0x00, 0xff]);
602 assert_eq!(format!("{data:?}"), "HexBinary(0735aacb00ff)",);
603
604 let data = HexBinary(vec![]);
606 assert_eq!(format!("{data:?}"), "HexBinary()",);
607 }
608
609 #[test]
610 fn hex_binary_implements_deref() {
611 let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
613 assert_eq!(*data, [7u8, 35, 49, 101, 0, 255]);
614
615 let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
617 assert_eq!(data.len(), 6);
618 let data_slice: &[u8] = &data;
619 assert_eq!(data_slice, &[7u8, 35, 49, 101, 0, 255]);
620 }
621
622 #[test]
623 fn hex_binary_implements_as_ref() {
624 let want = &[7u8, 35, 49, 101, 0, 255];
625 let data = HexBinary(want.to_vec());
626 assert_eq!(want, AsRef::<[u8]>::as_ref(&data));
627 assert_eq!(want, AsRef::<[u8]>::as_ref(&&data));
628 }
629
630 #[test]
633 fn hex_binary_implements_hash_eq() {
634 let a = HexBinary::from([0, 187, 61, 11, 250, 0]);
635 let b = HexBinary::from([16, 21, 33, 0, 255, 9]);
636 assert_hash_works!(a, b);
637 }
638
639 #[test]
640 fn hex_binary_implements_partial_eq_with_vector() {
641 let a = HexBinary(vec![5u8; 3]);
642 let b = vec![5u8; 3];
643 let c = vec![9u8; 3];
644 assert_eq!(a, b);
645 assert_eq!(b, a);
646 assert_ne!(a, c);
647 assert_ne!(c, a);
648 }
649
650 #[test]
651 fn hex_binary_implements_partial_eq_with_slice_and_array() {
652 let a = HexBinary(vec![0xAA, 0xBB]);
653
654 assert_eq!(a, b"\xAA\xBB" as &[u8]);
656 assert_eq!(b"\xAA\xBB" as &[u8], a);
657 assert_ne!(a, b"\x11\x22" as &[u8]);
658 assert_ne!(b"\x11\x22" as &[u8], a);
659
660 assert_eq!(a, b"\xAA\xBB");
662 assert_eq!(b"\xAA\xBB", a);
663 assert_ne!(a, b"\x11\x22");
664 assert_ne!(b"\x11\x22", a);
665
666 assert_eq!(a, [0xAA, 0xBB]);
668 assert_eq!([0xAA, 0xBB], a);
669 assert_ne!(a, [0x11, 0x22]);
670 assert_ne!([0x11, 0x22], a);
671 }
672}