bytekind/array/
mod.rs

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/// A wrapper around `[u8; N]` that allows control over the serialization format
12#[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    /// Consume `self` and return the underlying `[u8; N]`
101    #[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}