Skip to content

Commit e1f53b2

Browse files
committed
Support deserializing &'de [u8; N]
1 parent 677457b commit e1f53b2

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

src/bytearray.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use serde::ser::{Serialize, Serializer};
3535
/// # }
3636
/// ```
3737
#[derive(Copy, Clone, Eq, Ord)]
38+
#[cfg_attr(not(doc), repr(transparent))]
3839
pub struct ByteArray<const N: usize> {
3940
bytes: [u8; N],
4041
}
@@ -49,6 +50,10 @@ impl<const N: usize> ByteArray<N> {
4950
pub fn into_array(self) -> [u8; N] {
5051
self.bytes
5152
}
53+
54+
fn from_ref(bytes: &[u8; N]) -> &Self {
55+
unsafe { &*(bytes as *const [u8; N] as *const ByteArray<N>) }
56+
}
5257
}
5358

5459
impl<const N: usize> Debug for ByteArray<N> {
@@ -218,3 +223,39 @@ impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
218223
deserializer.deserialize_bytes(ByteArrayVisitor::<N>)
219224
}
220225
}
226+
227+
struct BorrowedByteArrayVisitor<const N: usize>;
228+
229+
impl<'de, const N: usize> Visitor<'de> for BorrowedByteArrayVisitor<N> {
230+
type Value = &'de ByteArray<N>;
231+
232+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
233+
write!(formatter, "a borrowed byte array of length {}", N)
234+
}
235+
236+
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
237+
where
238+
E: Error,
239+
{
240+
let borrowed_byte_array: &'de [u8; N] = v
241+
.try_into()
242+
.map_err(|_| E::invalid_length(v.len(), &self))?;
243+
Ok(ByteArray::from_ref(borrowed_byte_array))
244+
}
245+
246+
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
247+
where
248+
E: Error,
249+
{
250+
self.visit_borrowed_bytes(v.as_bytes())
251+
}
252+
}
253+
254+
impl<'a, 'de: 'a, const N: usize> Deserialize<'de> for &'a ByteArray<N> {
255+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
256+
where
257+
D: Deserializer<'de>,
258+
{
259+
deserializer.deserialize_bytes(BorrowedByteArrayVisitor::<N>)
260+
}
261+
}

src/de.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
8383
}
8484
}
8585

86+
impl<'de: 'a, 'a, const N: usize> Deserialize<'de> for &'a ByteArray<N> {
87+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88+
where
89+
D: Deserializer<'de>,
90+
{
91+
// Via the serde::Deserialize impl for &ByteArray.
92+
serde::Deserialize::deserialize(deserializer)
93+
}
94+
}
95+
8696
#[cfg(any(feature = "std", feature = "alloc"))]
8797
impl<'de> Deserialize<'de> for ByteBuf {
8898
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>

tests/test_derive.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ struct Test<'a> {
2222
#[serde(with = "serde_bytes")]
2323
byte_array: ByteArray<314>,
2424

25+
#[serde(with = "serde_bytes")]
26+
borrowed_byte_array: &'a ByteArray<314>,
27+
2528
#[serde(with = "serde_bytes")]
2629
byte_buf: ByteBuf,
2730

@@ -67,6 +70,7 @@ fn test() {
6770
vec: b"...".to_vec(),
6871
bytes: Bytes::new(b"..."),
6972
byte_array: ByteArray::new([0; 314]),
73+
borrowed_byte_array: &ByteArray::new([0; 314]),
7074
byte_buf: ByteBuf::from(b"...".as_ref()),
7175
cow_slice: Cow::Borrowed(b"..."),
7276
cow_bytes: Cow::Borrowed(Bytes::new(b"...")),
@@ -84,7 +88,7 @@ fn test() {
8488
&[
8589
Token::Struct {
8690
name: "Test",
87-
len: 15,
91+
len: 16,
8892
},
8993
Token::Str("slice"),
9094
Token::BorrowedBytes(b"..."),
@@ -96,6 +100,8 @@ fn test() {
96100
Token::BorrowedBytes(b"..."),
97101
Token::Str("byte_array"),
98102
Token::Bytes(&[0; 314]),
103+
Token::Str("borrowed_byte_array"),
104+
Token::BorrowedBytes(&[0; 314]),
99105
Token::Str("byte_buf"),
100106
Token::Bytes(b"..."),
101107
Token::Str("cow_slice"),

0 commit comments

Comments
 (0)