1use std::fmt;
2use std::ops::Deref;
3
4use schemars::JsonSchema;
5use serde::{de, ser, Deserialize, Deserializer, Serialize};
6
7use crate::{Binary, StdError, StdResult};
8
9#[derive(Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, JsonSchema)]
15pub struct HexBinary(#[schemars(with = "String")] Vec<u8>);
16
17impl HexBinary {
18 pub fn from_hex(input: &str) -> StdResult<Self> {
19 let vec = hex::decode(input).map_err(StdError::invalid_hex)?;
20 Ok(Self(vec))
21 }
22
23 pub fn to_hex(&self) -> String {
24 hex::encode(&self.0)
25 }
26
27 pub fn as_slice(&self) -> &[u8] {
28 self.0.as_slice()
29 }
30
31 pub fn to_array<const LENGTH: usize>(&self) -> StdResult<[u8; LENGTH]> {
53 if self.len() != LENGTH {
54 return Err(StdError::invalid_data_size(LENGTH, self.len()));
55 }
56
57 let mut out: [u8; LENGTH] = [0; LENGTH];
58 out.copy_from_slice(&self.0);
59 Ok(out)
60 }
61}
62
63impl fmt::Display for HexBinary {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 write!(f, "{}", self.to_hex())
66 }
67}
68
69impl fmt::Debug for HexBinary {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "HexBinary(")?;
74 for byte in self.0.iter() {
75 write!(f, "{:02x}", byte)?;
76 }
77 write!(f, ")")?;
78 Ok(())
79 }
80}
81
82impl From<&[u8]> for HexBinary {
83 fn from(binary: &[u8]) -> Self {
84 Self(binary.to_vec())
85 }
86}
87
88impl Deref for HexBinary {
94 type Target = [u8];
95
96 fn deref(&self) -> &Self::Target {
97 self.as_slice()
98 }
99}
100
101impl<const LENGTH: usize> From<&[u8; LENGTH]> for HexBinary {
103 fn from(source: &[u8; LENGTH]) -> Self {
104 Self(source.to_vec())
105 }
106}
107
108impl<const LENGTH: usize> From<[u8; LENGTH]> for HexBinary {
110 fn from(source: [u8; LENGTH]) -> Self {
111 Self(source.into())
112 }
113}
114
115impl From<Vec<u8>> for HexBinary {
116 fn from(vec: Vec<u8>) -> Self {
117 Self(vec)
118 }
119}
120
121impl From<HexBinary> for Vec<u8> {
122 fn from(original: HexBinary) -> Vec<u8> {
123 original.0
124 }
125}
126
127impl From<Binary> for HexBinary {
128 fn from(original: Binary) -> Self {
129 Self(original.into())
130 }
131}
132
133impl From<HexBinary> for Binary {
134 fn from(original: HexBinary) -> Binary {
135 Binary::from(original.0)
136 }
137}
138
139impl PartialEq<Vec<u8>> for HexBinary {
141 fn eq(&self, rhs: &Vec<u8>) -> bool {
142 self.0 == *rhs
144 }
145}
146
147impl PartialEq<HexBinary> for Vec<u8> {
149 fn eq(&self, rhs: &HexBinary) -> bool {
150 *self == rhs.0
152 }
153}
154
155impl PartialEq<&[u8]> for HexBinary {
157 fn eq(&self, rhs: &&[u8]) -> bool {
158 self.as_slice() == *rhs
160 }
161}
162
163impl PartialEq<HexBinary> for &[u8] {
165 fn eq(&self, rhs: &HexBinary) -> bool {
166 *self == rhs.as_slice()
168 }
169}
170
171impl<const LENGTH: usize> PartialEq<[u8; LENGTH]> for HexBinary {
173 fn eq(&self, rhs: &[u8; LENGTH]) -> bool {
174 self.as_slice() == rhs.as_slice()
175 }
176}
177
178impl<const LENGTH: usize> PartialEq<HexBinary> for [u8; LENGTH] {
180 fn eq(&self, rhs: &HexBinary) -> bool {
181 self.as_slice() == rhs.as_slice()
182 }
183}
184
185impl<const LENGTH: usize> PartialEq<&[u8; LENGTH]> for HexBinary {
187 fn eq(&self, rhs: &&[u8; LENGTH]) -> bool {
188 self.as_slice() == rhs.as_slice()
189 }
190}
191
192impl<const LENGTH: usize> PartialEq<HexBinary> for &[u8; LENGTH] {
194 fn eq(&self, rhs: &HexBinary) -> bool {
195 self.as_slice() == rhs.as_slice()
196 }
197}
198
199impl Serialize for HexBinary {
201 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
202 where
203 S: ser::Serializer,
204 {
205 serializer.serialize_str(&self.to_hex())
206 }
207}
208
209impl<'de> Deserialize<'de> for HexBinary {
211 fn deserialize<D>(deserializer: D) -> Result<HexBinary, D::Error>
212 where
213 D: Deserializer<'de>,
214 {
215 deserializer.deserialize_str(HexVisitor)
216 }
217}
218
219struct HexVisitor;
220
221impl<'de> de::Visitor<'de> for HexVisitor {
222 type Value = HexBinary;
223
224 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
225 formatter.write_str("valid hex encoded string")
226 }
227
228 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
229 where
230 E: de::Error,
231 {
232 match HexBinary::from_hex(v) {
233 Ok(data) => Ok(data),
234 Err(_) => Err(E::custom(format!("invalid hex: {}", v))),
235 }
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 use crate::{from_slice, to_vec, StdError};
244 use std::collections::hash_map::DefaultHasher;
245 use std::collections::HashSet;
246 use std::hash::{Hash, Hasher};
247
248 #[test]
249 fn from_hex_works() {
250 let data = HexBinary::from_hex("").unwrap();
251 assert_eq!(data, b"");
252 let data = HexBinary::from_hex("61").unwrap();
253 assert_eq!(data, b"a");
254 let data = HexBinary::from_hex("00").unwrap();
255 assert_eq!(data, b"\0");
256
257 let data = HexBinary::from_hex("68656c6c6f").unwrap();
258 assert_eq!(data, b"hello");
259 let data = HexBinary::from_hex("68656C6C6F").unwrap();
260 assert_eq!(data, b"hello");
261 let data = HexBinary::from_hex("72616e646f6d695a").unwrap();
262 assert_eq!(data.as_slice(), b"randomiZ");
263
264 match HexBinary::from_hex("123").unwrap_err() {
266 StdError::InvalidHex { msg, .. } => {
267 assert_eq!(msg, "Odd number of digits")
268 }
269 _ => panic!("Unexpected error type"),
270 }
271 match HexBinary::from_hex("efgh").unwrap_err() {
273 StdError::InvalidHex { msg, .. } => {
274 assert_eq!(msg, "Invalid character 'g' at position 2")
275 }
276 _ => panic!("Unexpected error type"),
277 }
278 match HexBinary::from_hex("0xaa").unwrap_err() {
280 StdError::InvalidHex { msg, .. } => {
281 assert_eq!(msg, "Invalid character 'x' at position 1")
282 }
283 _ => panic!("Unexpected error type"),
284 }
285 assert!(matches!(
287 HexBinary::from_hex("aa ").unwrap_err(),
288 StdError::InvalidHex { .. }
289 ));
290 assert!(matches!(
291 HexBinary::from_hex(" aa").unwrap_err(),
292 StdError::InvalidHex { .. }
293 ));
294 assert!(matches!(
295 HexBinary::from_hex("a a").unwrap_err(),
296 StdError::InvalidHex { .. }
297 ));
298 assert!(matches!(
299 HexBinary::from_hex(" aa ").unwrap_err(),
300 StdError::InvalidHex { .. }
301 ));
302 }
303
304 #[test]
305 fn to_hex_works() {
306 let binary: &[u8] = b"";
307 let encoded = HexBinary::from(binary).to_hex();
308 assert_eq!(encoded, "");
309
310 let binary: &[u8] = b"hello";
311 let encoded = HexBinary::from(binary).to_hex();
312 assert_eq!(encoded, "68656c6c6f");
313
314 let binary = vec![12u8, 187, 0, 17, 250, 1];
315 let encoded = HexBinary(binary).to_hex();
316 assert_eq!(encoded, "0cbb0011fa01");
317 }
318
319 #[test]
320 fn to_array_works() {
321 let binary = HexBinary::from(&[1, 2, 3]);
323 let array: [u8; 3] = binary.to_array().unwrap();
324 assert_eq!(array, [1, 2, 3]);
325
326 let binary = HexBinary::from(&[]);
328 let array: [u8; 0] = binary.to_array().unwrap();
329 assert_eq!(array, [] as [u8; 0]);
330
331 let binary = HexBinary::from(&[1, 2, 3]);
333 let error = binary.to_array::<8>().unwrap_err();
334 match error {
335 StdError::InvalidDataSize {
336 expected, actual, ..
337 } => {
338 assert_eq!(expected, 8);
339 assert_eq!(actual, 3);
340 }
341 err => panic!("Unexpected error: {:?}", err),
342 }
343
344 let binary =
346 HexBinary::from_hex("b75d7d24e428c7859440498efe7caa3997cefb08c99bdd581b6b1f9f866096f0")
347 .unwrap();
348 let array: [u8; 32] = binary.to_array().unwrap();
349 assert_eq!(
350 array,
351 [
352 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
353 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
354 0x86, 0x60, 0x96, 0xf0,
355 ]
356 );
357
358 let binary = HexBinary::from_hex(
360 "b75d7d24e428c7859440498efe7caa3997cefb08c99bdd581b6b1f9f866096f073c8c3b0316abe",
361 )
362 .unwrap();
363 let array: [u8; 39] = binary.to_array().unwrap();
364 assert_eq!(
365 array,
366 [
367 0xb7, 0x5d, 0x7d, 0x24, 0xe4, 0x28, 0xc7, 0x85, 0x94, 0x40, 0x49, 0x8e, 0xfe, 0x7c,
368 0xaa, 0x39, 0x97, 0xce, 0xfb, 0x08, 0xc9, 0x9b, 0xdd, 0x58, 0x1b, 0x6b, 0x1f, 0x9f,
369 0x86, 0x60, 0x96, 0xf0, 0x73, 0xc8, 0xc3, 0xb0, 0x31, 0x6a, 0xbe,
370 ]
371 );
372 }
373
374 #[test]
375 fn from_slice_works() {
376 let original: &[u8] = &[0u8, 187, 61, 11, 250, 0];
377 let binary: HexBinary = original.into();
378 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
379 }
380
381 #[test]
382 fn from_fixed_length_array_works() {
383 let original = &[];
384 let binary: HexBinary = original.into();
385 assert_eq!(binary.len(), 0);
386
387 let original = &[0u8];
388 let binary: HexBinary = original.into();
389 assert_eq!(binary.as_slice(), [0u8]);
390
391 let original = &[0u8, 187, 61, 11, 250, 0];
392 let binary: HexBinary = original.into();
393 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
394
395 let original = &[
396 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,
397 1, 1, 1,
398 ];
399 let binary: HexBinary = original.into();
400 assert_eq!(
401 binary.as_slice(),
402 [
403 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,
404 1, 1, 1, 1,
405 ]
406 );
407 }
408
409 #[test]
410 fn from_owned_fixed_length_array_works() {
411 let original = [];
412 let binary: HexBinary = original.into();
413 assert_eq!(binary.len(), 0);
414
415 let original = [0u8];
416 let binary: HexBinary = original.into();
417 assert_eq!(binary.as_slice(), [0u8]);
418
419 let original = [0u8, 187, 61, 11, 250, 0];
420 let binary: HexBinary = original.into();
421 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
422
423 let original = [
424 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,
425 1, 1, 1,
426 ];
427 let binary: HexBinary = original.into();
428 assert_eq!(
429 binary.as_slice(),
430 [
431 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,
432 1, 1, 1, 1,
433 ]
434 );
435 }
436
437 #[test]
438 fn from_literal_works() {
439 let a: HexBinary = b"".into();
440 assert_eq!(a.len(), 0);
441
442 let a: HexBinary = b".".into();
443 assert_eq!(a.len(), 1);
444
445 let a: HexBinary = b"...".into();
446 assert_eq!(a.len(), 3);
447
448 let a: HexBinary = b"...............................".into();
449 assert_eq!(a.len(), 31);
450
451 let a: HexBinary = b"................................".into();
452 assert_eq!(a.len(), 32);
453
454 let a: HexBinary = (b".................................").into();
455 assert_eq!(a.len(), 33);
456 }
457
458 #[test]
459 fn from_vec_works() {
460 let original = vec![0u8, 187, 61, 11, 250, 0];
461 let original_ptr = original.as_ptr();
462 let binary: HexBinary = original.into();
463 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
464 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
465 }
466
467 #[test]
468 fn into_vec_works() {
469 let original = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
471 let original_ptr = original.0.as_ptr();
472 let vec: Vec<u8> = original.into();
473 assert_eq!(vec.as_slice(), [0u8, 187, 61, 11, 250, 0]);
474 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
475
476 let original = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
478 let original_ptr = original.0.as_ptr();
479 let vec = Vec::<u8>::from(original);
480 assert_eq!(vec.as_slice(), [7u8, 35, 49, 101, 0, 255]);
481 assert_eq!(vec.as_ptr(), original_ptr, "vector must not be copied");
482 }
483
484 #[test]
485 fn from_binary_works() {
486 let original = Binary::from([0u8, 187, 61, 11, 250, 0]);
487 let original_ptr = original.as_ptr();
488 let binary: HexBinary = original.into();
489 assert_eq!(binary.as_slice(), [0u8, 187, 61, 11, 250, 0]);
490 assert_eq!(binary.0.as_ptr(), original_ptr, "vector must not be copied");
491 }
492
493 #[test]
494 fn into_binary_works() {
495 let original = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
497 let original_ptr = original.0.as_ptr();
498 let bin: Binary = original.into();
499 assert_eq!(bin.as_slice(), [0u8, 187, 61, 11, 250, 0]);
500 assert_eq!(bin.as_ptr(), original_ptr, "vector must not be copied");
501
502 let original = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
504 let original_ptr = original.0.as_ptr();
505 let bin = Binary::from(original);
506 assert_eq!(bin.as_slice(), [7u8, 35, 49, 101, 0, 255]);
507 assert_eq!(bin.as_ptr(), original_ptr, "vector must not be copied");
508 }
509
510 #[test]
511 fn serialization_works() {
512 let binary = HexBinary(vec![0u8, 187, 61, 11, 250, 0]);
513
514 let json = to_vec(&binary).unwrap();
515 let deserialized: HexBinary = from_slice(&json).unwrap();
516
517 assert_eq!(binary, deserialized);
518 }
519
520 #[test]
521 fn deserialize_from_valid_string() {
522 let hex = "00bb3d0bfa00";
523 let expected = vec![0u8, 187, 61, 11, 250, 0];
525
526 let serialized = to_vec(&hex).unwrap();
527 let deserialized: HexBinary = from_slice(&serialized).unwrap();
528 assert_eq!(expected, deserialized.as_slice());
529 }
530
531 #[test]
532 fn deserialize_from_invalid_string() {
533 let invalid_str = "**BAD!**";
534 let serialized = to_vec(&invalid_str).unwrap();
535 let res = from_slice::<HexBinary>(&serialized);
536 assert!(res.is_err());
537 }
538
539 #[test]
540 fn hex_binary_implements_debug() {
541 let data = HexBinary(vec![0x07, 0x35, 0xAA, 0xcb, 0x00, 0xff]);
543 assert_eq!(format!("{:?}", data), "HexBinary(0735aacb00ff)",);
544
545 let data = HexBinary(vec![]);
547 assert_eq!(format!("{:?}", data), "HexBinary()",);
548 }
549
550 #[test]
551 fn hex_binary_implements_deref() {
552 let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
554 assert_eq!(*data, [7u8, 35, 49, 101, 0, 255]);
555
556 let data = HexBinary(vec![7u8, 35, 49, 101, 0, 255]);
558 assert_eq!(data.len(), 6);
559 let data_slice: &[u8] = &data;
560 assert_eq!(data_slice, &[7u8, 35, 49, 101, 0, 255]);
561 }
562
563 #[test]
564 fn hex_binary_implements_hash() {
565 let a1 = HexBinary::from([0, 187, 61, 11, 250, 0]);
566 let mut hasher = DefaultHasher::new();
567 a1.hash(&mut hasher);
568 let a1_hash = hasher.finish();
569
570 let a2 = HexBinary::from([0, 187, 61, 11, 250, 0]);
571 let mut hasher = DefaultHasher::new();
572 a2.hash(&mut hasher);
573 let a2_hash = hasher.finish();
574
575 let b = HexBinary::from([16, 21, 33, 0, 255, 9]);
576 let mut hasher = DefaultHasher::new();
577 b.hash(&mut hasher);
578 let b_hash = hasher.finish();
579
580 assert_eq!(a1_hash, a2_hash);
581 assert_ne!(a1_hash, b_hash);
582 }
583
584 #[test]
586 fn hex_binary_can_be_used_in_hash_set() {
587 let a1 = HexBinary::from([0, 187, 61, 11, 250, 0]);
588 let a2 = HexBinary::from([0, 187, 61, 11, 250, 0]);
589 let b = HexBinary::from([16, 21, 33, 0, 255, 9]);
590
591 let mut set = HashSet::new();
592 set.insert(a1.clone());
593 set.insert(a2.clone());
594 set.insert(b.clone());
595 assert_eq!(set.len(), 2);
596
597 let set1 = HashSet::<HexBinary>::from_iter(vec![b.clone(), a1.clone()]);
598 let set2 = HashSet::from_iter(vec![a1, a2, b]);
599 assert_eq!(set1, set2);
600 }
601
602 #[test]
603 fn hex_binary_implements_partial_eq_with_vector() {
604 let a = HexBinary(vec![5u8; 3]);
605 let b = vec![5u8; 3];
606 let c = vec![9u8; 3];
607 assert_eq!(a, b);
608 assert_eq!(b, a);
609 assert_ne!(a, c);
610 assert_ne!(c, a);
611 }
612
613 #[test]
614 fn hex_binary_implements_partial_eq_with_slice_and_array() {
615 let a = HexBinary(vec![0xAA, 0xBB]);
616
617 assert_eq!(a, b"\xAA\xBB" as &[u8]);
619 assert_eq!(b"\xAA\xBB" as &[u8], a);
620 assert_ne!(a, b"\x11\x22" as &[u8]);
621 assert_ne!(b"\x11\x22" as &[u8], a);
622
623 assert_eq!(a, b"\xAA\xBB");
625 assert_eq!(b"\xAA\xBB", a);
626 assert_ne!(a, b"\x11\x22");
627 assert_ne!(b"\x11\x22", a);
628
629 assert_eq!(a, [0xAA, 0xBB]);
631 assert_eq!([0xAA, 0xBB], a);
632 assert_ne!(a, [0x11, 0x22]);
633 assert_ne!([0x11, 0x22], a);
634 }
635}