use crate::Bytes; use core::borrow::{Borrow, BorrowMut}; use core::cmp::Ordering; use core::convert::TryInto as _; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use core::ops::{Deref, DerefMut}; use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor}; use serde::ser::{Serialize, Serializer}; /// Wrapper around `[u8; N]` to serialize and deserialize efficiently. /// /// ``` /// use std::collections::HashMap; /// use std::io; /// /// use serde_bytes::ByteArray; /// /// fn deserialize_bytearrays() -> Result<(), bincode::error::DecodeError> { /// let example_data = [2, 2, 3, 116, 119, 111, 1, 3, 111, 110, 101]; /// /// let map: HashMap>; /// (map, _) = bincode::serde::decode_from_slice( /// &example_data, /// bincode::config::standard(), /// )?; /// /// println!("{:?}", map); /// /// Ok(()) /// } /// # /// # fn main() { /// # deserialize_bytearrays().unwrap(); /// # } /// ``` #[derive(Copy, Clone, Eq, Ord)] #[repr(transparent)] pub struct ByteArray { bytes: [u8; N], } impl ByteArray { /// Wrap an existing [array] into a `ByteArray`. pub const fn new(bytes: [u8; N]) -> Self { ByteArray { bytes } } /// Unwrap the byte array underlying this `ByteArray`. pub const fn into_array(self) -> [u8; N] { self.bytes } fn from_ref(bytes: &[u8; N]) -> &Self { unsafe { &*(bytes as *const [u8; N] as *const ByteArray) } } } impl Debug for ByteArray { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.bytes, f) } } impl Default for ByteArray { fn default() -> Self { ByteArray { bytes: [0; N] } } } impl AsRef<[u8; N]> for ByteArray { fn as_ref(&self) -> &[u8; N] { &self.bytes } } impl AsMut<[u8; N]> for ByteArray { fn as_mut(&mut self) -> &mut [u8; N] { &mut self.bytes } } impl Borrow<[u8; N]> for ByteArray { fn borrow(&self) -> &[u8; N] { &self.bytes } } impl BorrowMut<[u8; N]> for ByteArray { fn borrow_mut(&mut self) -> &mut [u8; N] { &mut self.bytes } } impl Deref for ByteArray { type Target = [u8; N]; fn deref(&self) -> &Self::Target { &self.bytes } } impl DerefMut for ByteArray { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.bytes } } impl Borrow for ByteArray { fn borrow(&self) -> &Bytes { Bytes::new(&self.bytes) } } impl BorrowMut for ByteArray { fn borrow_mut(&mut self) -> &mut Bytes { unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) } } } impl From<[u8; N]> for ByteArray { fn from(bytes: [u8; N]) -> Self { ByteArray { bytes } } } impl PartialEq for ByteArray where Rhs: ?Sized + Borrow<[u8; N]>, { fn eq(&self, other: &Rhs) -> bool { self.as_ref().eq(other.borrow()) } } impl PartialOrd for ByteArray where Rhs: ?Sized + Borrow<[u8; N]>, { fn partial_cmp(&self, other: &Rhs) -> Option { self.as_ref().partial_cmp(other.borrow()) } } impl Hash for ByteArray { fn hash(&self, state: &mut H) { self.bytes.hash(state); } } impl IntoIterator for ByteArray { type Item = u8; type IntoIter = <[u8; N] as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIterator::into_iter(self.bytes) } } impl<'a, const N: usize> IntoIterator for &'a ByteArray { type Item = &'a u8; type IntoIter = <&'a [u8; N] as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.bytes.iter() } } impl<'a, const N: usize> IntoIterator for &'a mut ByteArray { type Item = &'a mut u8; type IntoIter = <&'a mut [u8; N] as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.bytes.iter_mut() } } impl Serialize for ByteArray { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_bytes(&self.bytes) } } struct ByteArrayVisitor; impl<'de, const N: usize> Visitor<'de> for ByteArrayVisitor { type Value = ByteArray; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a byte array of length {N}") } fn visit_seq(self, mut seq: V) -> Result, V::Error> where V: SeqAccess<'de>, { let mut bytes = [0; N]; for (idx, byte) in bytes.iter_mut().enumerate() { *byte = seq .next_element()? .ok_or_else(|| V::Error::invalid_length(idx, &self))?; } Ok(ByteArray::new(bytes)) } fn visit_bytes(self, v: &[u8]) -> Result, E> where E: Error, { Ok(ByteArray { bytes: v .try_into() .map_err(|_| E::invalid_length(v.len(), &self))?, }) } fn visit_str(self, v: &str) -> Result, E> where E: Error, { self.visit_bytes(v.as_bytes()) } } impl<'de, const N: usize> Deserialize<'de> for ByteArray { fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { deserializer.deserialize_bytes(ByteArrayVisitor::) } } struct BorrowedByteArrayVisitor; impl<'de, const N: usize> Visitor<'de> for BorrowedByteArrayVisitor { type Value = &'de ByteArray; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a borrowed byte array of length {N}") } fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result where E: Error, { let borrowed_byte_array: &'de [u8; N] = v .try_into() .map_err(|_| E::invalid_length(v.len(), &self))?; Ok(ByteArray::from_ref(borrowed_byte_array)) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: Error, { self.visit_borrowed_bytes(v.as_bytes()) } } impl<'a, 'de: 'a, const N: usize> Deserialize<'de> for &'a ByteArray { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_bytes(BorrowedByteArrayVisitor::) } }