1#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
17use core::fmt::{LowerHex, UpperHex};
18#[cfg(any(feature = "std", feature = "alloc"))]
19use core::fmt::{self, Display, Debug, Formatter};
20#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
21use core::str::FromStr;
22use core::ops::{Index, IndexMut, RangeFull};
23#[cfg(feature = "alloc")]
24use alloc::vec::Vec;
25use core::borrow::{Borrow, BorrowMut};
26use core::ops::{
27 Range, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive, BitAndAssign, BitOrAssign,
28 BitXorAssign, BitAnd, BitOr, BitXor, Not,
29};
30use core::{slice, array};
31
32#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
33use crate::hex::{FromHex, ToHex, self};
34use crate::{Wrapper, WrapperMut};
35
36#[derive(Copy, Clone, Eq, PartialEq, Debug)]
38pub struct FromSliceError {
39 pub expected: usize,
41 pub actual: usize,
43}
44
45#[cfg(any(feature = "std", feature = "alloc"))]
46impl Display for FromSliceError {
47 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
48 write!(
49 f,
50 "the provided slice length {} doesn't match array size {}",
51 self.actual, self.expected
52 )
53 }
54}
55
56#[cfg(feature = "std")]
57impl std::error::Error for FromSliceError {}
58
59pub type Bytes<const LEN: usize> = Array<u8, LEN>;
65
66pub type Bytes4 = Array<u8, 4>;
72
73pub type Bytes16 = Array<u8, 16>;
79
80pub type Bytes20 = Array<u8, 20>;
86
87pub type Bytes32 = Array<u8, 32>;
93
94pub type Bytes32StrRev = Array<u8, 32, true>;
100
101pub type Bytes64 = Array<u8, 64>;
107
108#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
114pub struct Array<T, const LEN: usize, const REVERSE_STR: bool = false>([T; LEN]);
115
116impl<T, const LEN: usize, const REVERSE_STR: bool> Array<T, LEN, REVERSE_STR> {
117 pub fn with_fill(val: T) -> Self
121 where
122 T: Copy,
123 {
124 Self([val; LEN])
125 }
126
127 pub const fn from_array(inner: [T; LEN]) -> Self {
129 Self(inner)
130 }
131
132 #[inline]
134 pub fn as_slice(&self) -> &[T] {
135 self.as_ref()
136 }
137
138 #[inline]
140 pub fn as_slice_mut(&mut self) -> &mut [T] {
141 self.as_mut()
142 }
143
144 #[allow(clippy::wrong_self_convention)]
146 #[cfg(any(test, feature = "std", feature = "alloc"))]
147 pub fn to_vec(&self) -> Vec<T>
148 where
149 T: Clone,
150 {
151 self.0.to_vec()
152 }
153
154 pub fn iter(&self) -> slice::Iter<T> {
158 self.0.iter()
159 }
160
161 pub fn iter_mut(&mut self) -> slice::IterMut<T> {
165 self.0.iter_mut()
166 }
167}
168
169impl<const LEN: usize, const REVERSE_STR: bool> Array<u8, LEN, REVERSE_STR> {
170 #[cfg(feature = "rand")]
171 pub fn random() -> Self {
173 use rand::RngCore;
174 let mut entropy = [0u8; LEN];
175 rand::thread_rng().fill_bytes(&mut entropy);
176 Array::from_inner(entropy)
177 }
178
179 pub const fn zero() -> Self {
181 Self([0u8; LEN])
182 }
183
184 #[inline]
200 pub fn from_slice_unsafe(slice: impl AsRef<[u8]>) -> Self {
201 Self::copy_from_slice(slice).expect("slice length not matching type requirements")
202 }
203
204 #[inline]
206 pub fn to_byte_array(&self) -> [u8; LEN] {
207 self.0
208 }
209
210 #[inline]
212 pub fn from_byte_array(val: impl Into<[u8; LEN]>) -> Self {
213 Array::from_inner(val.into())
214 }
215}
216
217impl<const LEN: usize, const REVERSE_STR: bool> BitAnd for Array<u8, LEN, REVERSE_STR> {
218 type Output = Self;
219
220 fn bitand(mut self, rhs: Self) -> Self::Output {
221 self.bitand_assign(rhs);
222 self
223 }
224}
225
226impl<const LEN: usize, const REVERSE_STR: bool> BitAndAssign for Array<u8, LEN, REVERSE_STR> {
227 fn bitand_assign(&mut self, rhs: Self) {
228 self.0
229 .iter_mut()
230 .zip(rhs)
231 .for_each(|(a, b)| a.bitand_assign(b));
232 }
233}
234
235impl<const LEN: usize, const REVERSE_STR: bool> BitOr for Array<u8, LEN, REVERSE_STR> {
236 type Output = Self;
237
238 fn bitor(mut self, rhs: Self) -> Self::Output {
239 self.bitor_assign(rhs);
240 self
241 }
242}
243
244impl<const LEN: usize, const REVERSE_STR: bool> BitOrAssign for Array<u8, LEN, REVERSE_STR> {
245 fn bitor_assign(&mut self, rhs: Self) {
246 self.0
247 .iter_mut()
248 .zip(rhs)
249 .for_each(|(a, b)| a.bitor_assign(b));
250 }
251}
252
253impl<const LEN: usize, const REVERSE_STR: bool> BitXor for Array<u8, LEN, REVERSE_STR> {
254 type Output = Self;
255
256 fn bitxor(mut self, rhs: Self) -> Self::Output {
257 self.bitxor_assign(rhs);
258 self
259 }
260}
261
262impl<const LEN: usize, const REVERSE_STR: bool> BitXorAssign for Array<u8, LEN, REVERSE_STR> {
263 fn bitxor_assign(&mut self, rhs: Self) {
264 self.0
265 .iter_mut()
266 .zip(rhs)
267 .for_each(|(a, b)| a.bitxor_assign(b));
268 }
269}
270
271impl<const LEN: usize, const REVERSE_STR: bool> Not for Array<u8, LEN, REVERSE_STR> {
272 type Output = Self;
273
274 fn not(mut self) -> Self::Output {
275 self.0.iter_mut().for_each(|e| *e = e.not());
276 self
277 }
278}
279
280impl<T, const LEN: usize, const REVERSE_STR: bool> Array<T, LEN, REVERSE_STR>
281where
282 T: Default + Copy,
283{
284 #[deprecated(since = "4.2.0", note = "use copy_from_slice")]
287 pub fn from_slice(slice: impl AsRef<[T]>) -> Option<Self> {
288 let slice = slice.as_ref();
289 if slice.len() != LEN {
290 return None;
291 }
292 let mut inner = [T::default(); LEN];
293 inner.copy_from_slice(slice);
294 Some(Self(inner))
295 }
296
297 pub fn copy_from_slice(slice: impl AsRef<[T]>) -> Result<Self, FromSliceError> {
300 let slice = slice.as_ref();
301 let len = slice.len();
302 if len != LEN {
303 return Err(FromSliceError {
304 actual: len,
305 expected: LEN,
306 });
307 }
308 let mut inner = [T::default(); LEN];
309 inner.copy_from_slice(slice);
310 Ok(Self(inner))
311 }
312}
313
314impl<T, const LEN: usize, const REVERSE_STR: bool> Default for Array<T, LEN, REVERSE_STR>
315where
316 T: Default + Copy,
317{
318 fn default() -> Self {
319 let inner = [T::default(); LEN];
320 Self(inner)
321 }
322}
323
324impl<T, const LEN: usize, const REVERSE_STR: bool> From<[T; LEN]> for Array<T, LEN, REVERSE_STR> {
325 fn from(array: [T; LEN]) -> Self {
326 Array(array)
327 }
328}
329
330impl<T, const LEN: usize, const REVERSE_STR: bool> TryFrom<&[T]> for Array<T, LEN, REVERSE_STR>
331where
332 T: Copy + Default,
333{
334 type Error = FromSliceError;
335
336 fn try_from(value: &[T]) -> Result<Self, Self::Error> {
337 <[T; LEN]>::try_from(value)
338 .map_err(|_| FromSliceError {
339 actual: value.len(),
340 expected: LEN,
341 })
342 .map(Self)
343 }
344}
345
346impl<T, const LEN: usize, const REVERSE_STR: bool> AsRef<[T]> for Array<T, LEN, REVERSE_STR> {
347 #[inline]
348 fn as_ref(&self) -> &[T] {
349 self.0.as_ref()
350 }
351}
352
353impl<T, const LEN: usize, const REVERSE_STR: bool> AsMut<[T]> for Array<T, LEN, REVERSE_STR> {
354 #[inline]
355 fn as_mut(&mut self) -> &mut [T] {
356 self.0.as_mut()
357 }
358}
359
360impl<T, const LEN: usize, const REVERSE_STR: bool> Borrow<[T]> for Array<T, LEN, REVERSE_STR> {
361 #[inline]
362 fn borrow(&self) -> &[T] {
363 self.0.borrow()
364 }
365}
366
367impl<T, const LEN: usize, const REVERSE_STR: bool> BorrowMut<[T]> for Array<T, LEN, REVERSE_STR> {
368 #[inline]
369 fn borrow_mut(&mut self) -> &mut [T] {
370 self.0.borrow_mut()
371 }
372}
373
374impl<T, const LEN: usize, const REVERSE_STR: bool> Index<usize> for Array<T, LEN, REVERSE_STR> {
375 type Output = T;
376 #[inline]
377 fn index(&self, index: usize) -> &Self::Output {
378 &self.0[index]
379 }
380}
381
382impl<T, const LEN: usize, const REVERSE_STR: bool> Index<Range<usize>>
383 for Array<T, LEN, REVERSE_STR>
384{
385 type Output = [T];
386 #[inline]
387 fn index(&self, index: Range<usize>) -> &Self::Output {
388 &self.0[index]
389 }
390}
391
392impl<T, const LEN: usize, const REVERSE_STR: bool> Index<RangeTo<usize>>
393 for Array<T, LEN, REVERSE_STR>
394{
395 type Output = [T];
396 #[inline]
397 fn index(&self, index: RangeTo<usize>) -> &Self::Output {
398 &self.0[index]
399 }
400}
401
402impl<T, const LEN: usize, const REVERSE_STR: bool> Index<RangeFrom<usize>>
403 for Array<T, LEN, REVERSE_STR>
404{
405 type Output = [T];
406 #[inline]
407 fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
408 &self.0[index]
409 }
410}
411
412impl<T, const LEN: usize, const REVERSE_STR: bool> Index<RangeInclusive<usize>>
413 for Array<T, LEN, REVERSE_STR>
414{
415 type Output = [T];
416 #[inline]
417 fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
418 &self.0[index]
419 }
420}
421
422impl<T, const LEN: usize, const REVERSE_STR: bool> Index<RangeToInclusive<usize>>
423 for Array<T, LEN, REVERSE_STR>
424{
425 type Output = [T];
426 #[inline]
427 fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
428 &self.0[index]
429 }
430}
431
432impl<T, const LEN: usize, const REVERSE_STR: bool> Index<RangeFull> for Array<T, LEN, REVERSE_STR> {
433 type Output = [T];
434 #[inline]
435 fn index(&self, index: RangeFull) -> &Self::Output {
436 &self.0[index]
437 }
438}
439
440impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<usize> for Array<T, LEN, REVERSE_STR> {
441 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
442 &mut self.0[index]
443 }
444}
445
446impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<Range<usize>>
447 for Array<T, LEN, REVERSE_STR>
448{
449 #[inline]
450 fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
451 &mut self.0[index]
452 }
453}
454
455impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<RangeTo<usize>>
456 for Array<T, LEN, REVERSE_STR>
457{
458 #[inline]
459 fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
460 &mut self.0[index]
461 }
462}
463
464impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<RangeFrom<usize>>
465 for Array<T, LEN, REVERSE_STR>
466{
467 #[inline]
468 fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
469 &mut self.0[index]
470 }
471}
472
473impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<RangeInclusive<usize>>
474 for Array<T, LEN, REVERSE_STR>
475{
476 #[inline]
477 fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
478 &mut self.0[index]
479 }
480}
481
482impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<RangeToInclusive<usize>>
483 for Array<T, LEN, REVERSE_STR>
484{
485 #[inline]
486 fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
487 &mut self.0[index]
488 }
489}
490
491impl<T, const LEN: usize, const REVERSE_STR: bool> IndexMut<RangeFull>
492 for Array<T, LEN, REVERSE_STR>
493{
494 #[inline]
495 fn index_mut(&mut self, index: RangeFull) -> &mut Self::Output {
496 &mut self.0[index]
497 }
498}
499
500impl<T, const LEN: usize, const REVERSE_STR: bool> IntoIterator for Array<T, LEN, REVERSE_STR> {
501 type Item = T;
502 type IntoIter = array::IntoIter<T, LEN>;
503
504 fn into_iter(self) -> Self::IntoIter {
505 self.0.into_iter()
506 }
507}
508
509impl<T, const LEN: usize, const REVERSE_STR: bool> From<T> for Array<T, LEN, REVERSE_STR>
510where
511 T: Into<[T; LEN]>,
512{
513 fn from(array: T) -> Self {
514 Self(array.into())
515 }
516}
517
518impl<T, const LEN: usize, const REVERSE_STR: bool> Wrapper for Array<T, LEN, REVERSE_STR> {
519 type Inner = [T; LEN];
520
521 #[inline]
522 fn from_inner(inner: Self::Inner) -> Self {
523 Self(inner)
524 }
525
526 #[inline]
527 fn as_inner(&self) -> &Self::Inner {
528 &self.0
529 }
530
531 #[inline]
532 fn into_inner(self) -> Self::Inner {
533 self.0
534 }
535}
536
537impl<T, const LEN: usize, const REVERSE_STR: bool> WrapperMut for Array<T, LEN, REVERSE_STR> {
538 fn as_inner_mut(&mut self) -> &mut Self::Inner {
539 &mut self.0
540 }
541}
542
543#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
544impl<const LEN: usize, const REVERSE_STR: bool> Display for Array<u8, LEN, REVERSE_STR> {
545 #[inline]
546 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
547 LowerHex::fmt(self, f)
548 }
549}
550
551#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
552impl<const LEN: usize, const REVERSE_STR: bool> Debug for Array<u8, LEN, REVERSE_STR> {
553 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
554 write!(f, "Array<{}>({})", LEN, self.to_hex())
555 }
556}
557
558#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
559impl<const LEN: usize, const REVERSE_STR: bool> FromStr for Array<u8, LEN, REVERSE_STR> {
560 type Err = hex::Error;
561
562 fn from_str(s: &str) -> Result<Self, Self::Err> {
563 Self::from_hex(s)
564 }
565}
566
567#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
568impl<const LEN: usize, const REVERSE_STR: bool> FromHex for Array<u8, LEN, REVERSE_STR> {
569 fn from_byte_iter<I>(iter: I) -> Result<Self, hex::Error>
570 where
571 I: Iterator<Item = Result<u8, hex::Error>> + ExactSizeIterator + DoubleEndedIterator,
572 {
573 let mut vec = Vec::<u8>::from_byte_iter(iter)?;
574 if REVERSE_STR {
575 vec.reverse();
576 }
577 if vec.len() != LEN {
578 return Err(hex::Error::InvalidLength(LEN, vec.len()));
579 }
580 let mut id = [0u8; LEN];
581 id.copy_from_slice(&vec);
582 Ok(Array(id))
583 }
584}
585
586#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
587impl<const LEN: usize, const REVERSE_STR: bool> LowerHex for Array<u8, LEN, REVERSE_STR> {
588 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
589 let mut slice = self.into_inner();
590 if REVERSE_STR {
591 slice.reverse();
592 }
593 if f.alternate() {
594 write!(
595 f,
596 "{}..{}",
597 slice[..4].to_hex(),
598 slice[(slice.len() - 4)..].to_hex()
599 )
600 } else {
601 f.write_str(&slice.to_hex())
602 }
603 }
604}
605
606#[cfg(all(feature = "hex", any(feature = "std", feature = "alloc")))]
607impl<const LEN: usize, const REVERSE_STR: bool> UpperHex for Array<u8, LEN, REVERSE_STR> {
608 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
609 let mut slice = self.into_inner();
610 if REVERSE_STR {
611 slice.reverse();
612 }
613 if f.alternate() {
614 write!(
615 f,
616 "{}..{}",
617 slice[..4].to_hex().to_ascii_uppercase(),
618 slice[(slice.len() - 4)..].to_hex().to_ascii_uppercase()
619 )
620 } else {
621 f.write_str(&slice.to_hex().to_ascii_uppercase())
622 }
623 }
624}
625
626#[cfg(all(feature = "serde", feature = "hex"))]
627pub(crate) mod serde_helpers {
628 use core::fmt;
631 use serde::{Deserialize, Deserializer, Serializer, Serialize};
632 use serde_crate::de::{SeqAccess, Visitor};
633 use serde_crate::ser::SerializeTuple;
634
635 use crate::Array;
636 use crate::hex::{FromHex, ToHex};
637
638 impl<const LEN: usize, const REVERSE_STR: bool> Serialize for Array<u8, LEN, REVERSE_STR> {
639 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
640 where
641 S: Serializer,
642 {
643 if serializer.is_human_readable() {
644 serializer.serialize_str(&self.to_hex())
645 } else {
646 let mut ser = serializer.serialize_tuple(LEN)?;
647 for i in 0..LEN {
648 ser.serialize_element(&self.0[i])?;
649 }
650 ser.end()
651 }
652 }
653 }
654
655 impl<'de, const LEN: usize, const REVERSE_STR: bool> Deserialize<'de>
656 for Array<u8, LEN, REVERSE_STR>
657 {
658 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
659 where
660 D: Deserializer<'de>,
661 {
662 use serde::de::Error;
663 if deserializer.is_human_readable() {
664 String::deserialize(deserializer).and_then(|string| {
665 Self::from_hex(&string).map_err(|_| D::Error::custom("wrong hex data"))
666 })
667 } else {
668 struct ArrayVisitor<const LEN: usize>;
669
670 impl<'de, const LEN: usize> Visitor<'de> for ArrayVisitor<LEN> {
671 type Value = [u8; LEN];
672
673 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
674 write!(formatter, "an array of length {LEN}")
675 }
676
677 fn visit_seq<A>(self, mut seq: A) -> Result<[u8; LEN], A::Error>
678 where
679 A: SeqAccess<'de>,
680 {
681 let mut arr = [0; LEN];
682 for (i, el) in arr.iter_mut().enumerate() {
683 *el = seq
684 .next_element()?
685 .ok_or_else(|| Error::invalid_length(i, &self))?;
686 }
687 Ok(arr)
688 }
689 }
690
691 deserializer.deserialize_tuple(LEN, ArrayVisitor).map(Self)
692 }
693 }
694 }
695}
696
697#[deprecated(since = "4.2.0", note = "use ByteArray instead")]
699pub trait RawArray<const LEN: usize>: Sized {
700 fn from_raw_array(val: impl Into<[u8; LEN]>) -> Self;
702
703 fn to_raw_array(&self) -> [u8; LEN];
705}
706
707#[allow(deprecated)]
708impl<Id, const LEN: usize, const REVERSE_STR: bool> RawArray<LEN> for Id
709where
710 Id: Wrapper<Inner = Array<u8, LEN, REVERSE_STR>>,
711{
712 fn from_raw_array(val: impl Into<[u8; LEN]>) -> Self {
713 Self::from_inner(Array::from_inner(val.into()))
714 }
715
716 fn to_raw_array(&self) -> [u8; LEN] {
717 self.as_inner().into_inner()
718 }
719}
720
721pub trait ByteArray<const LEN: usize>: Sized {
723 fn from_byte_array(val: impl Into<[u8; LEN]>) -> Self;
725
726 fn from_slice(slice: impl AsRef<[u8]>) -> Result<Self, FromSliceError>;
729
730 fn from_slice_unsafe(slice: impl AsRef<[u8]>) -> Self;
737
738 fn to_byte_array(&self) -> [u8; LEN];
740}
741
742impl<Id, const LEN: usize, const REVERSE_STR: bool> ByteArray<LEN> for Id
743where
744 Id: Wrapper<Inner = Array<u8, LEN, REVERSE_STR>>,
745{
746 fn from_byte_array(val: impl Into<[u8; LEN]>) -> Self {
747 Self::from_inner(Array::from_inner(val.into()))
748 }
749
750 fn from_slice(slice: impl AsRef<[u8]>) -> Result<Self, FromSliceError> {
751 Array::try_from(slice.as_ref()).map(Self::from_inner)
752 }
753
754 fn from_slice_unsafe(slice: impl AsRef<[u8]>) -> Self {
755 Self::from_slice(slice).expect("slice length not matching type requirements")
756 }
757
758 fn to_byte_array(&self) -> [u8; LEN] {
759 self.as_inner().into_inner()
760 }
761}
762
763#[cfg(test)]
764mod test {
765 use core::str::FromStr;
766
767 use super::*;
768 use crate::Wrapper;
769 use crate::hex::FromHex;
770
771 #[test]
772 fn test_slice32_str() {
773 let s = "a3401bcceb26201b55978ff705fecf7d8a0a03598ebeccf2a947030b91a0ff53";
774 let slice32 = Bytes32::from_hex(s).unwrap();
775
776 assert_eq!(slice32[0], 0xa3);
777
778 assert_eq!(Bytes32::from_str(s), Ok(slice32));
779
780 assert_eq!(Bytes32::from_hex(&s.to_uppercase()), Ok(slice32));
781 assert_eq!(
782 Bytes32::from_str(&s[..30]),
783 Err(hex::Error::InvalidLength(32, 15))
784 );
785
786 assert_eq!(&slice32.to_string(), s);
787 assert_eq!(format!("{:x}", slice32), s);
788 assert_eq!(format!("{:X}", slice32), s.to_uppercase());
789 assert_eq!(format!("{:?}", slice32), format!("Array<32>({})", s));
790
791 #[cfg(feature = "serde")]
792 {
793 assert_eq!(
794 serde_json::to_string(&slice32).unwrap(),
795 format!(r#""{s}""#)
796 );
797 assert_eq!(
798 serde_json::from_str::<Bytes32>(&format!(r#""{s}""#)).unwrap(),
799 slice32
800 );
801 }
802 }
803
804 #[test]
805 fn test_slice32_rev_str() {
806 let s = "a3401bcceb26201b55978ff705fecf7d8a0a03598ebeccf2a947030b91a0ff53";
807 let slice32 = Bytes32StrRev::from_hex(s).unwrap();
808
809 assert_eq!(slice32[0], 0x53);
810
811 assert_eq!(Bytes32StrRev::from_str(s), Ok(slice32));
812
813 assert_eq!(Bytes32StrRev::from_hex(&s.to_uppercase()), Ok(slice32));
814 assert_eq!(
815 Bytes32StrRev::from_str(&s[..30]),
816 Err(hex::Error::InvalidLength(32, 15))
817 );
818
819 assert_eq!(&slice32.to_string(), s);
820 assert_eq!(format!("{:x}", slice32), s);
821 assert_eq!(format!("{:X}", slice32), s.to_uppercase());
822 assert_eq!(format!("{:?}", slice32), format!("Array<32>({})", s));
823
824 #[cfg(feature = "serde")]
825 {
826 assert_eq!(
827 serde_json::to_string(&slice32).unwrap(),
828 format!(r#""{s}""#)
829 );
830 assert_eq!(
831 serde_json::from_str::<Bytes32StrRev>(&format!(r#""{s}""#)).unwrap(),
832 slice32
833 );
834 }
835 }
836
837 #[test]
838 fn test_encoding() {
839 let s = "a3401bcceb26201b55978ff705fecf7d8a0a03598ebeccf2a947030b91a0ff53";
840 let slice32 = Array::from_hex(s).unwrap();
841
842 let data = [
843 0xa3, 0x40, 0x1b, 0xcc, 0xeb, 0x26, 0x20, 0x1b, 0x55, 0x97, 0x8f, 0xf7, 0x05, 0xfe,
844 0xcf, 0x7d, 0x8a, 0x0a, 0x03, 0x59, 0x8e, 0xbe, 0xcc, 0xf2, 0xa9, 0x47, 0x03, 0x0b,
845 0x91, 0xa0, 0xff, 0x53,
846 ];
847
848 assert_eq!(Bytes32::copy_from_slice(data), Ok(slice32));
849 assert_eq!(
850 Bytes32::copy_from_slice(&data[..30]),
851 Err(FromSliceError {
852 actual: 30,
853 expected: 32
854 })
855 );
856 assert_eq!(&slice32.to_vec(), &data);
857 assert_eq!(&slice32.as_inner()[..], &data);
858 assert_eq!(slice32.to_inner(), data);
859 assert_eq!(slice32.into_inner(), data);
860 }
861}