#![cfg_attr(not(test), no_std)]
use core::{
cmp::Ordering,
fmt::{self, Debug},
hash::{Hash, Hasher},
marker::PhantomData,
ops::{Deref, DerefMut},
ptr,
};
pub use heapless::consts;
pub use heapless::ArrayLength;
pub use typenum::{IsGreaterOrEqual, True, Unsigned};
use heapless::Vec;
use serde::{
de::{Deserialize, Deserializer, Visitor},
ser::{Serialize, Serializer},
};
#[derive(Clone, Default, Eq)]
pub struct Bytes<N: ArrayLength<u8>> {
bytes: Vec<u8, N>,
}
pub type Bytes8 = Bytes<consts::U8>;
pub type Bytes16 = Bytes<consts::U16>;
pub type Bytes32 = Bytes<consts::U32>;
pub type Bytes64 = Bytes<consts::U64>;
impl<N: ArrayLength<u8>> From<Vec<u8, N>> for Bytes<N> {
fn from(vec: Vec<u8, N>) -> Self {
Self { bytes: vec }
}
}
impl<N: ArrayLength<u8>> Bytes<N> {
pub fn new() -> Self {
Bytes::from(Vec::new())
}
pub fn from<T: Into<Vec<u8, N>>>(bytes: T) -> Self {
Bytes {
bytes: bytes.into(),
}
}
pub fn into_inner(self) -> Vec<u8, N> {
self.bytes
}
pub fn into_vec(self) -> Vec<u8, N> {
self.bytes
}
pub fn as_slice(&self) -> &[u8] {
self.bytes.as_ref()
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.bytes.as_mut()
}
pub fn try_convert_into<M: ArrayLength<u8>>(&self) -> Result<Bytes<M>, ()> {
Bytes::<M>::try_from_slice(self)
}
pub fn try_from_slice(slice: &[u8]) -> core::result::Result<Self, ()> {
let mut bytes = Vec::<u8, N>::new();
bytes.extend_from_slice(slice)?;
Ok(Self::from(bytes))
}
pub fn try_from<E>(
f: impl FnOnce(&mut [u8]) -> core::result::Result<usize, E>
)
-> core::result::Result<Self, E>
{
let mut data = Self::new();
data.resize_to_capacity();
let result = f(&mut data);
result.map(|count| {
data.resize_default(count).unwrap();
data
})
}
pub fn insert_slice_at(&mut self, slice: &[u8], at: usize) -> core::result::Result<(), ()> {
let l = slice.len();
let before = self.len();
self.bytes.resize_default(before + l)?;
let raw: &mut [u8] = &mut self.bytes;
raw.copy_within(at..before, at + l);
raw[at..][..l].copy_from_slice(slice);
Ok(())
}
pub fn insert(&mut self, index: usize, item: u8) -> Result<(), u8> {
self.insert_slice_at(&[item], index).map_err(|_| item)
}
pub fn remove(&mut self, index: usize) -> Result<u8, ()> {
if index < self.len() {
unsafe { Ok(self.remove_unchecked(index)) }
} else {
Err(())
}
}
pub(crate) unsafe fn remove_unchecked(&mut self, index: usize) -> u8 {
let p = (self.bytes.as_mut_ptr() as *mut u8).add(index);
let ret = ptr::read(p);
ptr::copy(p.offset(1), p, self.len() - index - 1);
self.resize_default(self.len() - 1).unwrap();
ret
}
pub fn resize_default(&mut self, new_len: usize) -> core::result::Result<(), ()> {
self.bytes.resize_default(new_len)
}
pub fn resize_to_capacity(&mut self) {
self.bytes.resize_default(self.bytes.capacity()).ok();
}
pub fn to_bytes<M>(&self) -> Bytes<M>
where
M: ArrayLength<u8> + IsGreaterOrEqual<N, Output = True>,
{
match Bytes::<M>::try_from_slice(self) {
Ok(byte_buf) => byte_buf,
_ => unreachable!(),
}
}
pub fn try_to_bytes<M>(&self) -> Result<Bytes<M>, ()>
where
M: ArrayLength<u8>,
{
Bytes::<M>::try_from_slice(self)
}
#[cfg(feature = "cbor")]
pub fn from_serialized<T>(t: &T) -> Self
where
T: Serialize,
{
let mut vec = Vec::<u8, N>::new();
vec.resize_default(N::to_usize()).unwrap();
let buffer = vec.deref_mut();
let writer = serde_cbor::ser::SliceWrite::new(buffer);
let mut ser = serde_cbor::Serializer::new(writer)
.packed_format()
;
t.serialize(&mut ser).unwrap();
let writer = ser.into_inner();
let size = writer.bytes_written();
vec.resize_default(size).unwrap();
Self::from(vec)
}
}
impl<N: ArrayLength<u8>> Debug for Bytes<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use core::ascii::escape_default;
f.write_str("b'")?;
for byte in &self.bytes {
for ch in escape_default(*byte) {
f.write_str(unsafe { core::str::from_utf8_unchecked(&[ch]) })?;
}
}
f.write_str("'")?;
Ok(())
}
}
impl<N: ArrayLength<u8>> AsRef<[u8]> for Bytes<N> {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl<N: ArrayLength<u8>> AsMut<[u8]> for Bytes<N> {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl<N: ArrayLength<u8>> Deref for Bytes<N> {
type Target = Vec<u8, N>;
fn deref(&self) -> &Self::Target {
&self.bytes
}
}
impl<N: ArrayLength<u8>> DerefMut for Bytes<N> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.bytes
}
}
impl<N: ArrayLength<u8>, Rhs> PartialEq<Rhs> for Bytes<N>
where
Rhs: ?Sized + AsRef<[u8]>,
{
fn eq(&self, other: &Rhs) -> bool {
self.as_ref().eq(other.as_ref())
}
}
impl<N: ArrayLength<u8>, Rhs> PartialOrd<Rhs> for Bytes<N>
where
Rhs: ?Sized + AsRef<[u8]>,
{
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
self.as_ref().partial_cmp(other.as_ref())
}
}
impl<N: ArrayLength<u8>> Hash for Bytes<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.bytes.hash(state);
}
}
impl<N: ArrayLength<u8>> IntoIterator for Bytes<N> {
type Item = u8;
type IntoIter = <Vec<u8, N> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.bytes.into_iter()
}
}
impl<'a, N: ArrayLength<u8>> IntoIterator for &'a Bytes<N> {
type Item = &'a u8;
type IntoIter = <&'a [u8] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.bytes.iter()
}
}
impl<'a, N: ArrayLength<u8>> IntoIterator for &'a mut Bytes<N> {
type Item = &'a mut u8;
type IntoIter = <&'a mut [u8] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.bytes.iter_mut()
}
}
impl<N> Serialize for Bytes<N>
where
N: ArrayLength<u8>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(self)
}
}
impl<'de, N> Deserialize<'de> for Bytes<N>
where
N: ArrayLength<u8>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct ValueVisitor<'de, N>(PhantomData<(&'de (), N)>);
impl<'de, N> Visitor<'de> for ValueVisitor<'de, N>
where
N: ArrayLength<u8>,
{
type Value = Bytes<N>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if v.len() > N::to_usize() {
return Err(E::invalid_length(v.len(), &self))?;
}
let mut buf: Vec<u8, N> = Vec::new();
match buf.extend_from_slice(v) {
Ok(()) => {}
Err(()) => {
return Err(E::invalid_length(v.len(), &self))?;
}
}
Ok(Bytes::<N>::from(buf))
}
}
deserializer.deserialize_bytes(ValueVisitor(PhantomData))
}
}
#[cfg(test)]
#[cfg(feature = "cbor")]
mod tests {
use super::*;
use heapless::consts;
#[test]
fn test_client_data_hash() {
let mut minimal = [
0x50u8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46,
];
let client_data_hash: Bytes<consts::U32> =
serde_cbor::de::from_mut_slice(&mut minimal).unwrap();
assert_eq!(client_data_hash, b"1234567890ABCDEF");
}
}