Skip to content

Commit 7ffee6f

Browse files
committed
Add byte array type
1 parent 6c699f2 commit 7ffee6f

File tree

5 files changed

+271
-3
lines changed

5 files changed

+271
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ edition = "2018"
99
keywords = ["serde", "serialization", "no_std", "bytes"]
1010
license = "MIT OR Apache-2.0"
1111
repository = "https://github.com/serde-rs/bytes"
12-
rust-version = "1.31"
12+
rust-version = "1.53"
1313

1414
[features]
1515
default = ["std"]

src/bytearray.rs

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
use crate::Bytes;
2+
use core::borrow::{Borrow, BorrowMut};
3+
use core::cmp::Ordering;
4+
use core::convert::TryInto;
5+
use core::fmt::{self, Debug};
6+
use core::hash::{Hash, Hasher};
7+
use core::ops::{Deref, DerefMut};
8+
9+
use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
10+
use serde::ser::{Serialize, Serializer};
11+
12+
/// Wrapper around `[u8; N]` to serialize and deserialize efficiently.
13+
///
14+
/// ```
15+
/// use std::collections::HashMap;
16+
/// use std::io;
17+
///
18+
/// use serde_bytes::ByteArray;
19+
///
20+
/// fn deserialize_bytearrays() -> bincode::Result<()> {
21+
/// let example_data = [
22+
/// 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
23+
/// 119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101
24+
/// ];
25+
///
26+
/// let map: HashMap<u32, ByteArray<3>> = bincode::deserialize(&example_data[..])?;
27+
///
28+
/// println!("{:?}", map);
29+
///
30+
/// Ok(())
31+
/// }
32+
/// #
33+
/// # fn main() {
34+
/// # deserialize_bytearrays().unwrap();
35+
/// # }
36+
/// ```
37+
#[derive(Clone, Eq, Ord)]
38+
pub struct ByteArray<const N: usize> {
39+
bytes: [u8; N],
40+
}
41+
42+
impl<const N: usize> ByteArray<N> {
43+
/// Transform an [array](https://doc.rust-lang.org/stable/std/primitive.array.html) to the equivalent `ByteArray`
44+
pub fn new(bytes: [u8; N]) -> Self {
45+
Self { bytes }
46+
}
47+
48+
/// Wrap existing bytes into a `ByteArray`
49+
pub fn from<T: Into<[u8; N]>>(bytes: T) -> Self {
50+
Self {
51+
bytes: bytes.into(),
52+
}
53+
}
54+
55+
/// Unwraps the byte array underlying this `ByteArray`
56+
pub fn into_array(self) -> [u8; N] {
57+
self.bytes
58+
}
59+
}
60+
61+
impl<const N: usize> Debug for ByteArray<N> {
62+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63+
Debug::fmt(&self.bytes, f)
64+
}
65+
}
66+
67+
impl<const N: usize> AsRef<[u8; N]> for ByteArray<N> {
68+
fn as_ref(&self) -> &[u8; N] {
69+
&self.bytes
70+
}
71+
}
72+
impl<const N: usize> AsMut<[u8; N]> for ByteArray<N> {
73+
fn as_mut(&mut self) -> &mut [u8; N] {
74+
&mut self.bytes
75+
}
76+
}
77+
78+
impl<const N: usize> Borrow<[u8; N]> for ByteArray<N> {
79+
fn borrow(&self) -> &[u8; N] {
80+
&self.bytes
81+
}
82+
}
83+
impl<const N: usize> BorrowMut<[u8; N]> for ByteArray<N> {
84+
fn borrow_mut(&mut self) -> &mut [u8; N] {
85+
&mut self.bytes
86+
}
87+
}
88+
89+
impl<const N: usize> Deref for ByteArray<N> {
90+
type Target = [u8; N];
91+
92+
fn deref(&self) -> &Self::Target {
93+
&self.bytes
94+
}
95+
}
96+
97+
impl<const N: usize> DerefMut for ByteArray<N> {
98+
fn deref_mut(&mut self) -> &mut Self::Target {
99+
&mut self.bytes
100+
}
101+
}
102+
103+
impl<const N: usize> Borrow<Bytes> for ByteArray<N> {
104+
fn borrow(&self) -> &Bytes {
105+
Bytes::new(&self.bytes)
106+
}
107+
}
108+
109+
impl<const N: usize> BorrowMut<Bytes> for ByteArray<N> {
110+
fn borrow_mut(&mut self) -> &mut Bytes {
111+
unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
112+
}
113+
}
114+
115+
impl<Rhs, const N: usize> PartialEq<Rhs> for ByteArray<N>
116+
where
117+
Rhs: ?Sized + Borrow<[u8; N]>,
118+
{
119+
fn eq(&self, other: &Rhs) -> bool {
120+
self.as_ref().eq(other.borrow())
121+
}
122+
}
123+
124+
impl<Rhs, const N: usize> PartialOrd<Rhs> for ByteArray<N>
125+
where
126+
Rhs: ?Sized + Borrow<[u8; N]>,
127+
{
128+
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
129+
self.as_ref().partial_cmp(other.borrow())
130+
}
131+
}
132+
133+
impl<const N: usize> Hash for ByteArray<N> {
134+
fn hash<H: Hasher>(&self, state: &mut H) {
135+
self.bytes.hash(state);
136+
}
137+
}
138+
139+
impl<const N: usize> IntoIterator for ByteArray<N> {
140+
type Item = u8;
141+
type IntoIter = <[u8; N] as IntoIterator>::IntoIter;
142+
143+
fn into_iter(self) -> Self::IntoIter {
144+
IntoIterator::into_iter(self.bytes)
145+
}
146+
}
147+
148+
impl<'a, const N: usize> IntoIterator for &'a ByteArray<N> {
149+
type Item = &'a u8;
150+
type IntoIter = <&'a [u8; N] as IntoIterator>::IntoIter;
151+
152+
fn into_iter(self) -> Self::IntoIter {
153+
self.bytes.iter()
154+
}
155+
}
156+
157+
impl<'a, const N: usize> IntoIterator for &'a mut ByteArray<N> {
158+
type Item = &'a mut u8;
159+
type IntoIter = <&'a mut [u8; N] as IntoIterator>::IntoIter;
160+
161+
fn into_iter(self) -> Self::IntoIter {
162+
self.bytes.iter_mut()
163+
}
164+
}
165+
166+
impl<const N: usize> Serialize for ByteArray<N> {
167+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
168+
where
169+
S: Serializer,
170+
{
171+
serializer.serialize_bytes(&self.bytes)
172+
}
173+
}
174+
175+
struct ByteArrayVisitor<const N: usize>;
176+
177+
impl<'de, const N: usize> Visitor<'de> for ByteArrayVisitor<N> {
178+
type Value = ByteArray<N>;
179+
180+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
181+
write!(formatter, "a byte array of length {}", N)
182+
}
183+
184+
fn visit_seq<V>(self, mut seq: V) -> Result<ByteArray<N>, V::Error>
185+
where
186+
V: SeqAccess<'de>,
187+
{
188+
let mut bytes = [0; N];
189+
190+
for (idx, byte) in bytes.iter_mut().enumerate() {
191+
*byte = seq
192+
.next_element()?
193+
.ok_or_else(|| V::Error::invalid_length(idx, &self))?;
194+
}
195+
196+
Ok(ByteArray::from(bytes))
197+
}
198+
199+
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteArray<N>, E>
200+
where
201+
E: Error,
202+
{
203+
Ok(ByteArray {
204+
bytes: v
205+
.try_into()
206+
.map_err(|_| E::invalid_length(v.len(), &self))?,
207+
})
208+
}
209+
210+
fn visit_str<E>(self, v: &str) -> Result<ByteArray<N>, E>
211+
where
212+
E: Error,
213+
{
214+
self.visit_bytes(v.as_bytes())
215+
}
216+
}
217+
218+
impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
219+
fn deserialize<D>(deserializer: D) -> Result<ByteArray<N>, D::Error>
220+
where
221+
D: Deserializer<'de>,
222+
{
223+
deserializer.deserialize_bytes(ByteArrayVisitor::<N>)
224+
}
225+
}

src/de.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::Bytes;
1+
use crate::{ByteArray, Bytes};
22
use core::fmt;
33
use core::marker::PhantomData;
44
use serde::de::{Error, Visitor};
@@ -63,6 +63,26 @@ impl<'de: 'a, 'a> Deserialize<'de> for &'a Bytes {
6363
}
6464
}
6565

66+
impl<'de, const N: usize> Deserialize<'de> for [u8; N] {
67+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68+
where
69+
D: Deserializer<'de>,
70+
{
71+
let arr: ByteArray<N> = serde::Deserialize::deserialize(deserializer)?;
72+
Ok(*arr)
73+
}
74+
}
75+
76+
impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
77+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
78+
where
79+
D: Deserializer<'de>,
80+
{
81+
// Via the serde::Deserialize impl for ByteArray
82+
serde::Deserialize::deserialize(deserializer)
83+
}
84+
}
85+
6686
#[cfg(any(feature = "std", feature = "alloc"))]
6787
impl<'de> Deserialize<'de> for ByteBuf {
6888
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>

src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
//!
2525
//! #[serde(with = "serde_bytes")]
2626
//! byte_buf: Vec<u8>,
27+
//!
28+
//! #[serde(with = "serde_bytes")]
29+
//! byte_array: [u8; 314],
2730
//! }
2831
//! ```
2932
@@ -36,6 +39,7 @@
3639
clippy::needless_doctest_main
3740
)]
3841

42+
mod bytearray;
3943
mod bytes;
4044
mod de;
4145
mod ser;
@@ -51,6 +55,7 @@ use serde::Deserializer;
5155

5256
use serde::Serializer;
5357

58+
pub use crate::bytearray::ByteArray;
5459
pub use crate::bytes::Bytes;
5560
pub use crate::de::Deserialize;
5661
pub use crate::ser::Serialize;

src/ser.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::Bytes;
1+
use crate::{ByteArray, Bytes};
22
use serde::Serializer;
33

44
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -51,6 +51,24 @@ impl Serialize for Bytes {
5151
}
5252
}
5353

54+
impl<const N: usize> Serialize for [u8; N] {
55+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
56+
where
57+
S: Serializer,
58+
{
59+
serializer.serialize_bytes(self)
60+
}
61+
}
62+
63+
impl<const N: usize> Serialize for ByteArray<N> {
64+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65+
where
66+
S: Serializer,
67+
{
68+
serializer.serialize_bytes(&**self)
69+
}
70+
}
71+
5472
#[cfg(any(feature = "std", feature = "alloc"))]
5573
impl Serialize for ByteBuf {
5674
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

0 commit comments

Comments
 (0)