1use core::fmt::{Debug, Formatter};
2use core::hash::Hash;
3use core::marker::PhantomData;
4
5use crate::Format;
6
7#[cfg(feature = "proptest")]
8mod proptest;
9mod serde;
10
11#[derive(Copy)]
13pub struct ByteArray<F: Format, const N: usize> {
14 inner: [u8; N],
15 _marker: PhantomData<F>,
16}
17
18impl<F: Format, const N: usize> Debug for ByteArray<F, N> {
19 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
20 f.debug_struct("ByteArray")
21 .field("inner", &self.inner)
22 .finish_non_exhaustive()
23 }
24}
25impl<F: Format, const N: usize> Clone for ByteArray<F, N> {
26 fn clone(&self) -> Self {
27 Self {
28 inner: self.inner,
29 _marker: PhantomData,
30 }
31 }
32}
33
34impl<F: Format, G: Format, const N: usize> PartialEq<ByteArray<F, N>> for ByteArray<G, N> {
35 fn eq(&self, other: &ByteArray<F, N>) -> bool {
36 self.inner.eq(&other.inner)
37 }
38}
39
40impl<F: Format, const N: usize> Eq for ByteArray<F, N> {}
41
42impl<F: Format, const N: usize> PartialEq<&[u8; N]> for ByteArray<F, N> {
43 fn eq(&self, other: &&[u8; N]) -> bool {
44 self.inner.eq(*other)
45 }
46}
47
48impl<F: Format, const N: usize> PartialEq<[u8; N]> for ByteArray<F, N> {
49 fn eq(&self, other: &[u8; N]) -> bool {
50 self.inner.eq(other)
51 }
52}
53
54impl<F: Format, const N: usize> PartialEq<&[u8]> for ByteArray<F, N> {
55 fn eq(&self, other: &&[u8]) -> bool {
56 self.inner.eq(other)
57 }
58}
59
60impl<F: Format, const N: usize> PartialEq<[u8]> for ByteArray<F, N> {
61 fn eq(&self, other: &[u8]) -> bool {
62 self.inner.eq(other)
63 }
64}
65
66impl<F: Format, const N: usize> PartialOrd for ByteArray<F, N> {
67 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
68 <[u8; N]>::partial_cmp(&self.inner, &other.inner)
69 }
70}
71
72impl<F: Format, const N: usize> Ord for ByteArray<F, N> {
73 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
74 <[u8; N]>::cmp(&self.inner, &other.inner)
75 }
76}
77
78impl<F: Format, const N: usize> From<[u8; N]> for ByteArray<F, N> {
79 fn from(inner: [u8; N]) -> Self {
80 Self {
81 inner,
82 _marker: PhantomData,
83 }
84 }
85}
86
87impl<F: Format, const N: usize> From<ByteArray<F, N>> for [u8; N] {
88 fn from(array: ByteArray<F, N>) -> Self {
89 array.inner
90 }
91}
92
93impl<F: Format, const N: usize> Hash for ByteArray<F, N> {
94 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
95 <[u8; N]>::hash(&self.inner, state);
96 }
97}
98
99impl<F: Format, const N: usize> ByteArray<F, N> {
100 #[inline]
102 pub fn into_inner(self) -> [u8; N] {
103 self.inner
104 }
105}
106
107impl<F: Format, const N: usize> AsRef<[u8]> for ByteArray<F, N> {
108 fn as_ref(&self) -> &[u8] {
109 &self.inner
110 }
111}
112
113impl<F: Format, const N: usize> AsMut<[u8]> for ByteArray<F, N> {
114 fn as_mut(&mut self) -> &mut [u8] {
115 &mut self.inner
116 }
117}
118
119impl<F: Format, const N: usize> AsRef<[u8; N]> for ByteArray<F, N> {
120 fn as_ref(&self) -> &[u8; N] {
121 &self.inner
122 }
123}
124
125impl<F: Format, const N: usize> AsMut<[u8; N]> for ByteArray<F, N> {
126 fn as_mut(&mut self) -> &mut [u8; N] {
127 &mut self.inner
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use serde_json::{from_value, json};
134
135 use crate::{HexString, Plain};
136
137 use super::*;
138
139 #[test]
140 fn check_eq_impls() {
141 let byte_array: ByteArray<Plain, 4> = ByteArray::from([0, 1, 2, 3]);
142
143 let first = byte_array == [0, 1, 2, 3];
144 assert!(first);
145
146 let slice: &[u8] = &[0, 1, 2, 3];
147 let second = byte_array == slice;
148 assert!(second);
149
150 let array_ref: &[u8; 4] = &[0, 1, 2, 3];
151 let third = byte_array == array_ref;
152 assert!(third);
153
154 let fourth = byte_array == byte_array;
155 assert!(fourth);
156 }
157
158 #[test]
159 fn parses_with_leading_0x() {
160 let byte_array: ByteArray<HexString, 1> = from_value(json!("0x00")).unwrap();
161 assert_eq!(byte_array, [0]);
162 }
163}