alloy_primitives/bits/
macros.rs

1/// Wrap a fixed-size byte array in a newtype, delegating all methods to the
2/// underlying [`crate::FixedBytes`].
3///
4/// This functionally creates a new named `FixedBytes` that cannot be
5/// type-confused for another named `FixedBytes`.
6///
7/// **NOTE:** This macro currently requires:
8/// - `#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]` at the top level of the crate.
9/// - The `derive_more` crate in scope.
10///
11/// # Examples
12///
13/// ```
14/// use alloy_primitives::wrap_fixed_bytes;
15///
16/// // These hashes are the same length, and have the same functionality, but
17/// // are distinct types
18/// wrap_fixed_bytes!(pub struct KeccakOutput<32>;);
19/// wrap_fixed_bytes!(pub struct MerkleTreeItem<32>;);
20/// ```
21#[macro_export]
22macro_rules! wrap_fixed_bytes {
23    (
24        $(#[$attrs:meta])*
25        $vis:vis struct $name:ident<$n:literal>;
26    ) => {
27        $crate::wrap_fixed_bytes!(
28            extra_derives: [$crate::private::derive_more::Display],
29            $(#[$attrs])*
30            $vis struct $name<$n>;
31        );
32    };
33
34    (
35        extra_derives: [$($extra_derives:path),* $(,)?],
36        $(#[$attrs:meta])*
37        $vis:vis struct $name:ident<$n:literal>;
38    ) => {
39        $(#[$attrs])*
40        #[derive(
41            Clone,
42            Copy,
43            Default,
44            PartialEq,
45            Eq,
46            PartialOrd,
47            Ord,
48            Hash,
49            $crate::private::derive_more::AsMut,
50            $crate::private::derive_more::AsRef,
51            $crate::private::derive_more::BitAnd,
52            $crate::private::derive_more::BitAndAssign,
53            $crate::private::derive_more::BitOr,
54            $crate::private::derive_more::BitOrAssign,
55            $crate::private::derive_more::BitXor,
56            $crate::private::derive_more::BitXorAssign,
57            $crate::private::derive_more::Not,
58            $crate::private::derive_more::Deref,
59            $crate::private::derive_more::DerefMut,
60            $crate::private::derive_more::From,
61            $crate::private::derive_more::FromStr,
62            $crate::private::derive_more::Index,
63            $crate::private::derive_more::IndexMut,
64            $crate::private::derive_more::Into,
65            $crate::private::derive_more::IntoIterator,
66            $crate::private::derive_more::LowerHex,
67            $crate::private::derive_more::UpperHex,
68            $(
69                $extra_derives,
70            )*
71        )]
72        #[repr(transparent)]
73        $vis struct $name(#[into_iterator(owned, ref, ref_mut)] pub $crate::FixedBytes<$n>);
74
75        impl $crate::private::From<[u8; $n]> for $name {
76            #[inline]
77            fn from(value: [u8; $n]) -> Self {
78                Self($crate::FixedBytes(value))
79            }
80        }
81
82        impl $crate::private::From<$name> for [u8; $n] {
83            #[inline]
84            fn from(value: $name) -> Self {
85                value.0 .0
86            }
87        }
88
89        impl<'a> $crate::private::From<&'a [u8; $n]> for $name {
90            #[inline]
91            fn from(value: &'a [u8; $n]) -> Self {
92                Self($crate::FixedBytes(*value))
93            }
94        }
95
96        impl<'a> $crate::private::From<&'a mut [u8; $n]> for $name {
97            #[inline]
98            fn from(value: &'a mut [u8; $n]) -> Self {
99                Self($crate::FixedBytes(*value))
100            }
101        }
102
103        impl $crate::private::TryFrom<&[u8]> for $name {
104            type Error = $crate::private::core::array::TryFromSliceError;
105
106            #[inline]
107            fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
108                <&Self as $crate::private::TryFrom<&[u8]>>::try_from(slice).copied()
109            }
110        }
111
112        impl $crate::private::TryFrom<&mut [u8]> for $name {
113            type Error = $crate::private::core::array::TryFromSliceError;
114
115            #[inline]
116            fn try_from(slice: &mut [u8]) -> Result<Self, Self::Error> {
117                <Self as $crate::private::TryFrom<&[u8]>>::try_from(&*slice)
118            }
119        }
120
121        impl<'a> $crate::private::TryFrom<&'a [u8]> for &'a $name {
122            type Error = $crate::private::core::array::TryFromSliceError;
123
124            #[inline]
125            #[allow(unsafe_code)]
126            fn try_from(slice: &'a [u8]) -> Result<&'a $name, Self::Error> {
127                // SAFETY: `$name` is `repr(transparent)` for `FixedBytes<$n>`
128                // and consequently `[u8; $n]`
129                <&[u8; $n] as $crate::private::TryFrom<&[u8]>>::try_from(slice)
130                    .map(|array_ref| unsafe { $crate::private::core::mem::transmute(array_ref) })
131            }
132        }
133
134        impl<'a> $crate::private::TryFrom<&'a mut [u8]> for &'a mut $name {
135            type Error = $crate::private::core::array::TryFromSliceError;
136
137            #[inline]
138            #[allow(unsafe_code)]
139            fn try_from(slice: &'a mut [u8]) -> Result<&'a mut $name, Self::Error> {
140                // SAFETY: `$name` is `repr(transparent)` for `FixedBytes<$n>`
141                // and consequently `[u8; $n]`
142                <&mut [u8; $n] as $crate::private::TryFrom<&mut [u8]>>::try_from(slice)
143                    .map(|array_ref| unsafe { $crate::private::core::mem::transmute(array_ref) })
144            }
145        }
146
147        impl $crate::private::AsRef<[u8; $n]> for $name {
148            #[inline]
149            fn as_ref(&self) -> &[u8; $n] {
150                &self.0 .0
151            }
152        }
153
154        impl $crate::private::AsMut<[u8; $n]> for $name {
155            #[inline]
156            fn as_mut(&mut self) -> &mut [u8; $n] {
157                &mut self.0 .0
158            }
159        }
160
161        impl $crate::private::AsRef<[u8]> for $name {
162            #[inline]
163            fn as_ref(&self) -> &[u8] {
164                &self.0 .0
165            }
166        }
167
168        impl $crate::private::AsMut<[u8]> for $name {
169            #[inline]
170            fn as_mut(&mut self) -> &mut [u8] {
171                &mut self.0 .0
172            }
173        }
174
175        impl $crate::private::core::fmt::Debug for $name {
176            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177                $crate::private::core::fmt::Debug::fmt(&self.0, f)
178            }
179        }
180
181        $crate::impl_fb_traits!($name, $n);
182        $crate::impl_rlp!($name, $n);
183        $crate::impl_serde!($name);
184        $crate::impl_allocative!($name);
185        $crate::impl_arbitrary!($name, $n);
186        $crate::impl_rand!($name);
187
188        impl $name {
189            /// Array of Zero bytes.
190            pub const ZERO: Self = Self($crate::FixedBytes::ZERO);
191
192            /// Wraps the given byte array in this type.
193            #[inline]
194            pub const fn new(bytes: [u8; $n]) -> Self {
195                Self($crate::FixedBytes(bytes))
196            }
197
198            /// Creates a new byte array with the last byte set to `x`.
199            #[inline]
200            pub const fn with_last_byte(x: u8) -> Self {
201                Self($crate::FixedBytes::with_last_byte(x))
202            }
203
204            /// Creates a new byte array where all bytes are set to `byte`.
205            #[inline]
206            pub const fn repeat_byte(byte: u8) -> Self {
207                Self($crate::FixedBytes::repeat_byte(byte))
208            }
209
210            /// Returns the size of this array in bytes.
211            #[inline]
212            pub const fn len_bytes() -> usize {
213                $n
214            }
215
216            $crate::impl_getrandom!();
217            $crate::impl_rand!();
218
219            /// Create a new byte array from the given slice `src`.
220            ///
221            /// For a fallible version, use the `TryFrom<&[u8]>` implementation.
222            ///
223            /// # Note
224            ///
225            /// The given bytes are interpreted in big endian order.
226            ///
227            /// # Panics
228            ///
229            /// If the length of `src` and the number of bytes in `Self` do not match.
230            #[inline]
231            #[track_caller]
232            pub fn from_slice(src: &[u8]) -> Self {
233                match Self::try_from(src) {
234                    Ok(x) => x,
235                    Err(_) => panic!("cannot convert a slice of length {} to {}", src.len(), stringify!($name)),
236                }
237            }
238
239            /// Create a new byte array from the given slice `src`, left-padding it
240            /// with zeroes if necessary.
241            ///
242            /// # Note
243            ///
244            /// The given bytes are interpreted in big endian order.
245            ///
246            /// # Panics
247            ///
248            /// Panics if `src.len() > N`.
249            #[inline]
250            #[track_caller]
251            pub fn left_padding_from(value: &[u8]) -> Self {
252                Self($crate::FixedBytes::left_padding_from(value))
253            }
254
255            /// Create a new byte array from the given slice `src`, right-padding it
256            /// with zeroes if necessary.
257            ///
258            /// # Note
259            ///
260            /// The given bytes are interpreted in big endian order.
261            ///
262            /// # Panics
263            ///
264            /// Panics if `src.len() > N`.
265            #[inline]
266            #[track_caller]
267            pub fn right_padding_from(value: &[u8]) -> Self {
268                Self($crate::FixedBytes::right_padding_from(value))
269            }
270
271            /// Returns the inner bytes array.
272            #[inline]
273            pub const fn into_array(self) -> [u8; $n] {
274                self.0 .0
275            }
276
277            /// Returns `true` if all bits set in `b` are also set in `self`.
278            #[inline]
279            pub fn covers(&self, b: &Self) -> bool {
280                &(*b & *self) == b
281            }
282
283            /// Compile-time equality. NOT constant-time equality.
284            pub const fn const_eq(&self, other: &Self) -> bool {
285                self.0.const_eq(&other.0)
286            }
287
288            /// Computes the bitwise AND of two `FixedBytes`.
289            pub const fn bit_and(self, rhs: Self) -> Self {
290                Self(self.0.bit_and(rhs.0))
291            }
292
293            /// Computes the bitwise OR of two `FixedBytes`.
294            pub const fn bit_or(self, rhs: Self) -> Self {
295                Self(self.0.bit_or(rhs.0))
296            }
297
298            /// Computes the bitwise XOR of two `FixedBytes`.
299            pub const fn bit_xor(self, rhs: Self) -> Self {
300                Self(self.0.bit_xor(rhs.0))
301            }
302        }
303    };
304}
305
306// Extra traits that cannot be derived automatically
307#[doc(hidden)]
308#[macro_export]
309macro_rules! impl_fb_traits {
310    (impl<$($const:ident)?> Borrow<$t:ty> for $b:ty) => {
311        impl<$($const N: usize)?> $crate::private::Borrow<$t> for $b {
312            #[inline]
313            fn borrow(&self) -> &$t {
314                $crate::private::Borrow::borrow(&self.0)
315            }
316        }
317    };
318
319    (impl<$($const:ident)?> BorrowMut<$t:ty> for $b:ty) => {
320        impl<$($const N: usize)?> $crate::private::BorrowMut<$t> for $b {
321            #[inline]
322            fn borrow_mut(&mut self) -> &mut $t {
323                $crate::private::BorrowMut::borrow_mut(&mut self.0)
324            }
325        }
326    };
327
328    (unsafe impl<$lt:lifetime, $($const:ident)?> From<$a:ty> for $b:ty) => {
329        impl<$lt, $($const N: usize)?> $crate::private::From<$a> for $b {
330            #[inline]
331            #[allow(unsafe_code)]
332            fn from(value: $a) -> $b {
333                // SAFETY: guaranteed by caller
334                unsafe { $crate::private::core::mem::transmute::<$a, $b>(value) }
335            }
336        }
337    };
338
339    (impl<$($const:ident)?> cmp::$tr:ident<$a:ty> for $b:ty where fn $fn:ident -> $ret:ty $(, [$e:expr])?) => {
340        impl<$($const N: usize)?> $crate::private::$tr<$a> for $b {
341            #[inline]
342            fn $fn(&self, other: &$a) -> $ret {
343                $crate::private::$tr::$fn(&self.0 $([$e])?, other)
344            }
345        }
346
347        impl<$($const N: usize)?> $crate::private::$tr<$b> for $a {
348            #[inline]
349            fn $fn(&self, other: &$b) -> $ret {
350                $crate::private::$tr::$fn(self, &other.0 $([$e])?)
351            }
352        }
353
354        impl<$($const N: usize)?> $crate::private::$tr<&$a> for $b {
355            #[inline]
356            fn $fn(&self, other: &&$a) -> $ret {
357                $crate::private::$tr::$fn(&self.0 $([$e])?, *other)
358            }
359        }
360
361        impl<$($const N: usize)?> $crate::private::$tr<$b> for &$a {
362            #[inline]
363            fn $fn(&self, other: &$b) -> $ret {
364                $crate::private::$tr::$fn(*self, &other.0 $([$e])?)
365            }
366        }
367
368        impl<$($const N: usize)?> $crate::private::$tr<$a> for &$b {
369            #[inline]
370            fn $fn(&self, other: &$a) -> $ret {
371                $crate::private::$tr::$fn(&self.0 $([$e])?, other)
372            }
373        }
374
375        impl<$($const N: usize)?> $crate::private::$tr<&$b> for $a {
376            #[inline]
377            fn $fn(&self, other: &&$b) -> $ret {
378                $crate::private::$tr::$fn(self, &other.0 $([$e])?)
379            }
380        }
381    };
382
383    ($t:ty, $n:tt $(, $const:ident)?) => {
384        // Borrow is not automatically implemented for references
385        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8]>        for $t);
386        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8]>        for &$t);
387        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8]>        for &mut $t);
388        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8; $n]>    for $t);
389        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8; $n]>    for &$t);
390        $crate::impl_fb_traits!(impl<$($const)?> Borrow<[u8; $n]>    for &mut $t);
391
392        $crate::impl_fb_traits!(impl<$($const)?> BorrowMut<[u8]>     for $t);
393        $crate::impl_fb_traits!(impl<$($const)?> BorrowMut<[u8]>     for &mut $t);
394        $crate::impl_fb_traits!(impl<$($const)?> BorrowMut<[u8; $n]> for $t);
395        $crate::impl_fb_traits!(impl<$($const)?> BorrowMut<[u8; $n]> for &mut $t);
396
397        // Implement conversion traits for references with `mem::transmute`
398        // SAFETY: `repr(transparent)`
399        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a [u8; $n]>     for &'a $t);
400        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a mut [u8; $n]> for &'a $t);
401        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a mut [u8; $n]> for &'a mut $t);
402
403        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a $t>           for &'a [u8; $n]);
404        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a mut $t>       for &'a [u8; $n]);
405        $crate::impl_fb_traits!(unsafe impl<'a, $($const)?> From<&'a mut $t>       for &'a mut [u8; $n]);
406
407        // Implement PartialEq, PartialOrd, with slice and array
408        $crate::impl_fb_traits!(impl<$($const)?> cmp::PartialEq<[u8]> for $t where fn eq -> bool);
409        $crate::impl_fb_traits!(impl<$($const)?> cmp::PartialEq<[u8; $n]> for $t where fn eq -> bool);
410        $crate::impl_fb_traits!(
411            impl<$($const)?> cmp::PartialOrd<[u8]> for $t
412            where
413                fn partial_cmp -> $crate::private::Option<$crate::private::Ordering>,
414                [..] // slices $t
415        );
416
417        impl<$($const N: usize)?> $crate::hex::FromHex for $t {
418            type Error = $crate::hex::FromHexError;
419
420            #[inline]
421            fn from_hex<T: $crate::private::AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
422                $crate::hex::decode_to_array(hex).map(Self::new)
423            }
424        }
425    };
426}
427
428#[doc(hidden)]
429#[macro_export]
430#[cfg(feature = "getrandom")]
431macro_rules! impl_getrandom {
432    () => {
433        /// Creates a new fixed byte array with the default cryptographic random number
434        /// generator.
435        ///
436        /// This is `rand::thread_rng` if the "rand" and "std" features are enabled, otherwise
437        /// it uses `getrandom::getrandom`. Both are cryptographically secure.
438        #[inline]
439        #[track_caller]
440        #[cfg_attr(docsrs, doc(cfg(feature = "getrandom")))]
441        pub fn random() -> Self {
442            Self($crate::FixedBytes::random())
443        }
444
445        /// Tries to create a new fixed byte array with the default cryptographic random number
446        /// generator.
447        ///
448        /// See [`random`](Self::random) for more details.
449        #[inline]
450        #[cfg_attr(docsrs, doc(cfg(feature = "getrandom")))]
451        pub fn try_random() -> $crate::private::Result<Self, $crate::private::getrandom::Error> {
452            $crate::FixedBytes::try_random().map(Self)
453        }
454
455        /// Fills this fixed byte array with the default cryptographic random number generator.
456        ///
457        /// See [`random`](Self::random) for more details.
458        #[inline]
459        #[track_caller]
460        #[cfg_attr(docsrs, doc(cfg(feature = "getrandom")))]
461        pub fn randomize(&mut self) {
462            self.0.randomize();
463        }
464
465        /// Tries to fill this fixed byte array with the default cryptographic random number
466        /// generator.
467        ///
468        /// See [`random`](Self::random) for more details.
469        #[inline]
470        #[cfg_attr(docsrs, doc(cfg(feature = "getrandom")))]
471        pub fn try_randomize(
472            &mut self,
473        ) -> $crate::private::Result<(), $crate::private::getrandom::Error> {
474            self.0.try_randomize()
475        }
476    };
477}
478
479#[doc(hidden)]
480#[macro_export]
481#[cfg(not(feature = "getrandom"))]
482macro_rules! impl_getrandom {
483    () => {};
484}
485
486#[doc(hidden)]
487#[macro_export]
488#[cfg(feature = "rand")]
489macro_rules! impl_rand {
490    () => {
491        /// Creates a new fixed byte array with the given random number generator.
492        #[inline]
493        #[doc(alias = "random_using")]
494        #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
495        pub fn random_with<R: $crate::private::rand::RngCore + ?Sized>(rng: &mut R) -> Self {
496            Self($crate::FixedBytes::random_with(rng))
497        }
498
499        /// Fills this fixed byte array with the given random number generator.
500        #[inline]
501        #[doc(alias = "randomize_using")]
502        #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
503        pub fn randomize_with<R: $crate::private::rand::RngCore + ?Sized>(&mut self, rng: &mut R) {
504            self.0.randomize_with(rng);
505        }
506    };
507
508    ($t:ty) => {
509        #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
510        impl $crate::private::rand::distributions::Distribution<$t>
511            for $crate::private::rand::distributions::Standard
512        {
513            #[inline]
514            fn sample<R: $crate::private::rand::Rng + ?Sized>(&self, rng: &mut R) -> $t {
515                <$t>::random_with(rng)
516            }
517        }
518    };
519}
520
521#[doc(hidden)]
522#[macro_export]
523#[cfg(not(feature = "rand"))]
524macro_rules! impl_rand {
525    ($($t:tt)*) => {};
526}
527
528#[doc(hidden)]
529#[macro_export]
530#[cfg(feature = "rlp")]
531macro_rules! impl_rlp {
532    ($t:ty, $n:literal) => {
533        #[cfg_attr(docsrs, doc(cfg(feature = "rlp")))]
534        impl $crate::private::alloy_rlp::Decodable for $t {
535            #[inline]
536            fn decode(buf: &mut &[u8]) -> $crate::private::alloy_rlp::Result<Self> {
537                $crate::private::alloy_rlp::Decodable::decode(buf).map(Self)
538            }
539        }
540
541        #[cfg_attr(docsrs, doc(cfg(feature = "rlp")))]
542        impl $crate::private::alloy_rlp::Encodable for $t {
543            #[inline]
544            fn length(&self) -> usize {
545                $crate::private::alloy_rlp::Encodable::length(&self.0)
546            }
547
548            #[inline]
549            fn encode(&self, out: &mut dyn $crate::private::alloy_rlp::BufMut) {
550                $crate::private::alloy_rlp::Encodable::encode(&self.0, out)
551            }
552        }
553
554        $crate::private::alloy_rlp::impl_max_encoded_len!($t, {
555            $n + $crate::private::alloy_rlp::length_of_length($n)
556        });
557    };
558}
559
560#[doc(hidden)]
561#[macro_export]
562#[cfg(not(feature = "rlp"))]
563macro_rules! impl_rlp {
564    ($t:ty, $n:literal) => {};
565}
566
567#[doc(hidden)]
568#[macro_export]
569#[cfg(feature = "allocative")]
570macro_rules! impl_allocative {
571    ($t:ty) => {
572        #[cfg_attr(docsrs, doc(cfg(feature = "allocative")))]
573        impl $crate::private::allocative::Allocative for $t {
574            #[inline]
575            fn visit<'a, 'b: 'a>(&self, visitor: &'a mut $crate::private::allocative::Visitor<'b>) {
576                $crate::private::allocative::Allocative::visit(&self.0, visitor)
577            }
578        }
579    };
580}
581
582#[doc(hidden)]
583#[macro_export]
584#[cfg(not(feature = "allocative"))]
585macro_rules! impl_allocative {
586    ($t:ty) => {};
587}
588
589#[doc(hidden)]
590#[macro_export]
591#[cfg(feature = "serde")]
592macro_rules! impl_serde {
593    ($t:ty) => {
594        #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
595        impl $crate::private::serde::Serialize for $t {
596            #[inline]
597            fn serialize<S: $crate::private::serde::Serializer>(
598                &self,
599                serializer: S,
600            ) -> Result<S::Ok, S::Error> {
601                $crate::private::serde::Serialize::serialize(&self.0, serializer)
602            }
603        }
604
605        #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
606        impl<'de> $crate::private::serde::Deserialize<'de> for $t {
607            #[inline]
608            fn deserialize<D: $crate::private::serde::Deserializer<'de>>(
609                deserializer: D,
610            ) -> Result<Self, D::Error> {
611                $crate::private::serde::Deserialize::deserialize(deserializer).map(Self)
612            }
613        }
614    };
615}
616
617#[doc(hidden)]
618#[macro_export]
619#[cfg(not(feature = "serde"))]
620macro_rules! impl_serde {
621    ($t:ty) => {};
622}
623
624#[doc(hidden)]
625#[macro_export]
626#[cfg(feature = "arbitrary")]
627macro_rules! impl_arbitrary {
628    ($t:ty, $n:literal) => {
629        #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
630        impl<'a> $crate::private::arbitrary::Arbitrary<'a> for $t {
631            #[inline]
632            fn arbitrary(u: &mut $crate::private::arbitrary::Unstructured<'a>) -> $crate::private::arbitrary::Result<Self> {
633                <$crate::FixedBytes<$n> as $crate::private::arbitrary::Arbitrary>::arbitrary(u).map(Self)
634            }
635
636            #[inline]
637            fn arbitrary_take_rest(u: $crate::private::arbitrary::Unstructured<'a>) -> $crate::private::arbitrary::Result<Self> {
638                <$crate::FixedBytes<$n> as $crate::private::arbitrary::Arbitrary>::arbitrary_take_rest(u).map(Self)
639            }
640
641            #[inline]
642            fn size_hint(depth: usize) -> (usize, Option<usize>) {
643                <$crate::FixedBytes<$n> as $crate::private::arbitrary::Arbitrary>::size_hint(depth)
644            }
645        }
646
647        #[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
648        impl $crate::private::proptest::arbitrary::Arbitrary for $t {
649            type Parameters = <$crate::FixedBytes<$n> as $crate::private::proptest::arbitrary::Arbitrary>::Parameters;
650            type Strategy = $crate::private::proptest::strategy::Map<
651                <$crate::FixedBytes<$n> as $crate::private::proptest::arbitrary::Arbitrary>::Strategy,
652                fn($crate::FixedBytes<$n>) -> Self,
653            >;
654
655            #[inline]
656            fn arbitrary() -> Self::Strategy {
657                use $crate::private::proptest::strategy::Strategy;
658                <$crate::FixedBytes<$n> as $crate::private::proptest::arbitrary::Arbitrary>::arbitrary()
659                    .prop_map(Self)
660            }
661
662            #[inline]
663            fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
664                use $crate::private::proptest::strategy::Strategy;
665                <$crate::FixedBytes<$n> as $crate::private::proptest::arbitrary::Arbitrary>::arbitrary_with(args)
666                    .prop_map(Self)
667            }
668        }
669    };
670}
671
672#[doc(hidden)]
673#[macro_export]
674#[cfg(not(feature = "arbitrary"))]
675macro_rules! impl_arbitrary {
676    ($t:ty, $n:literal) => {};
677}
678
679macro_rules! fixed_bytes_macros {
680    ($d:tt $($(#[$attr:meta])* macro $name:ident($ty:ident $($rest:tt)*);)*) => {$(
681        /// Converts a sequence of string literals containing hex-encoded data
682        #[doc = concat!(
683            "into a new [`", stringify!($ty), "`][crate::", stringify!($ty), "] at compile time.\n",
684        )]
685        ///
686        /// If the input is empty, a zero-initialized array is returned.
687        ///
688        /// See [`hex!`](crate::hex!) for more information.
689        ///
690        /// # Examples
691        ///
692        /// ```
693        #[doc = concat!("use alloy_primitives::{", stringify!($name), ", ", stringify!($ty), "};")]
694        ///
695        #[doc = concat!("const ZERO: ", stringify!($ty $($rest)*), " = ", stringify!($name), "!();")]
696        #[doc = concat!("assert_eq!(ZERO, ", stringify!($ty), "::ZERO);")]
697        ///
698        /// # stringify!(
699        #[doc = concat!("let byte_array: ", stringify!($ty), " = ", stringify!($name), "!(\"0x0123abcd…\");")]
700        /// # );
701        /// ```
702        $(#[$attr])*
703        #[macro_export]
704        macro_rules! $name {
705            () => {
706                $crate::$ty::ZERO
707            };
708
709            ($d ($d t:tt)+) => {
710                $crate::$ty::new($crate::hex!($d ($d t)+))
711            };
712        }
713    )*};
714}
715
716fixed_bytes_macros! { $
717    macro address(Address);
718
719    macro b64(B64);
720
721    macro b128(B128);
722
723    macro b256(B256);
724
725    macro b512(B512);
726
727    macro bloom(Bloom);
728
729    macro fixed_bytes(FixedBytes<0>); // <0> is just for the doctest
730}
731
732/// Converts a sequence of string literals containing hex-encoded data into a
733/// new [`Bytes`][crate::Bytes] at compile time.
734///
735/// If the input is empty, an empty instance is returned.
736///
737/// See [`hex!`](crate::hex!) for more information.
738///
739/// # Examples
740///
741/// ```
742/// use alloy_primitives::{bytes, Bytes};
743///
744/// static MY_BYTES: Bytes = bytes!("0x0123" "0xabcd");
745/// assert_eq!(MY_BYTES, Bytes::from(&[0x01, 0x23, 0xab, 0xcd]));
746/// ```
747#[macro_export]
748macro_rules! bytes {
749    () => {
750        $crate::Bytes::new()
751    };
752
753    ($($s:literal)+) => {const {
754        $crate::Bytes::from_static(&$crate::hex!($($s)+))
755    }};
756
757    [$($inner:expr),+ $(,)?] => {const {
758        $crate::Bytes::from_static(&[$($inner),+])
759    }};
760
761    [$inner:expr; $size:literal] => {const {
762        $crate::Bytes::from_static(&[$inner; $size])
763    }};
764}
765
766#[cfg(test)]
767mod tests {
768    use crate::{hex, Address, Bytes, FixedBytes};
769
770    #[test]
771    fn bytes_macros() {
772        static B1: Bytes = bytes!("010203040506070809");
773        static B2: Bytes = bytes![1, 2, 3, 4, 5, 6, 7, 8, 9];
774        static B3: Bytes = bytes![1, 2, 3, 4, 5, 6, 7, 8, 9,];
775
776        assert_eq!(B1, B2);
777        assert_eq!(B1, B3);
778
779        static B4: Bytes = bytes!("0000");
780        static B5: Bytes = bytes![0; 2];
781        static B6: Bytes = bytes![0, 0];
782        assert_eq!(B4, B5);
783        assert_eq!(B4, B6);
784    }
785
786    #[test]
787    fn fixed_byte_macros() {
788        const A0: Address = address!();
789        assert_eq!(A0, Address::ZERO);
790
791        const A1: Address = address!("0x0102030405060708090a0b0c0d0e0f1011121314");
792        const A2: Address = Address(fixed_bytes!("0x0102030405060708090a0b0c0d0e0f1011121314"));
793        const A3: Address = Address(FixedBytes(hex!("0x0102030405060708090a0b0c0d0e0f1011121314")));
794        assert_eq!(A1, A2);
795        assert_eq!(A1, A3);
796        assert_eq!(A1, hex!("0x0102030405060708090a0b0c0d0e0f1011121314"));
797
798        static B: Bytes = bytes!("0x112233");
799        assert_eq!(B[..], [0x11, 0x22, 0x33]);
800
801        static EMPTY_BYTES1: Bytes = bytes!();
802        static EMPTY_BYTES2: Bytes = bytes!("");
803        assert!(EMPTY_BYTES1.is_empty());
804        assert_eq!(EMPTY_BYTES1, Bytes::new());
805        assert_eq!(EMPTY_BYTES1, EMPTY_BYTES2);
806    }
807}