Remove Deref impl,

Add `From` implementations
This commit is contained in:
Sosthène Guédon
2024-06-20 09:57:50 +02:00
committed by sosthene-nitrokey
parent 7840edb274
commit 33277be39c
+180 -119
View File
@@ -10,7 +10,6 @@ use core::{
fmt::{self, Debug},
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
ptr,
};
use heapless::Vec;
@@ -20,7 +19,7 @@ use serde::{
ser::{Serialize, Serializer},
};
#[derive(Clone, Default, Eq)]
#[derive(Clone, Default, Eq, Ord)]
pub struct Bytes<const N: usize> {
bytes: Vec<u8, N>,
}
@@ -36,84 +35,150 @@ impl<const N: usize> From<Vec<u8, N>> for Bytes<N> {
}
}
impl<const N: usize> From<Bytes<N>> for Vec<u8, N> {
fn from(value: Bytes<N>) -> Self {
value.bytes
}
}
impl<const N: usize> TryFrom<&[u8]> for Bytes<N> {
type Error = ();
fn try_from(value: &[u8]) -> Result<Self, ()> {
Ok(Self {
bytes: Vec::from_slice(value)?,
})
}
}
impl<const N: usize> Bytes<N> {
/// Construct a new, empty `Bytes<N>`.
pub fn new() -> Self {
Bytes::from(Vec::new())
}
/// Unwraps the Vec<u8, N>, same as `into_vec`.
pub fn into_inner(self) -> Vec<u8, N> {
self.bytes
pub fn as_ptr(&self) -> *const u8 {
self.bytes.as_ptr()
}
/// Unwraps the Vec<u8, N>, same as `into_inner`.
pub fn into_vec(self) -> Vec<u8, N> {
self.bytes
pub fn as_mut_ptr(&mut self) -> *mut u8 {
self.bytes.as_mut_ptr()
}
/// Returns an immutable slice view.
// Add as inherent method as it's annoying to import AsSlice.
pub fn as_slice(&self) -> &[u8] {
self.bytes.as_ref()
self.bytes.as_slice()
}
/// Returns a mutable slice view.
// Add as inherent method as it's annoying to import AsSlice.
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.bytes.as_mut()
self.bytes.as_mut_slice()
}
/// Low-noise conversion between lengths.
///
/// We can't implement TryInto since it would clash with blanket implementations.
pub fn try_convert_into<const M: usize>(&self) -> Result<Bytes<M>, ()> {
Bytes::<M>::from_slice(self)
pub const fn capacity(&self) -> usize {
self.bytes.capacity()
}
// 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 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 clear(&mut self) {
self.bytes.clear()
}
/// Some APIs offer an interface of the form `f(&mut [u8]) -> Result<usize, E>`,
/// with the contract that the Ok-value signals how many bytes were written.
///
/// This constructor allows wrapping such interfaces in a more ergonomic way,
/// returning a Bytes willed using `f`.
///
/// It seems it's not possible to do this as an actual `TryFrom` implementation.
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
})
#[deprecated(note = "Panics when out of capacity")]
pub fn extend<I: IntoIterator<Item = u8>>(&mut self, iter: I) {
self.bytes.extend(iter)
}
// pub fn try_from<'a, E>(
// f: impl FnOnce(&'a mut [u8]) -> core::result::Result<&'a mut [u8], E>
// )
// -> core::result::Result<Self, E>
// {
pub fn extend_from_slice(&mut self, other: &[u8]) -> Result<(), ()> {
self.bytes.extend_from_slice(other)
}
pub fn pop(&mut self) -> Option<u8> {
self.bytes.pop()
}
pub fn push(&mut self, byte: u8) -> Result<(), ()> {
self.bytes.push(byte).map_err(drop)
}
pub unsafe fn pop_unchecked(&mut self) -> u8 {
unsafe { self.bytes.pop_unchecked() }
}
pub unsafe fn push_unchecked(&mut self, byte: u8) {
unsafe {
self.bytes.push_unchecked(byte);
}
}
pub fn truncate(&mut self, len: usize) {
self.bytes.truncate(len)
}
pub fn resize(&mut self, new_len: usize, value: u8) -> Result<(), ()> {
self.bytes.resize(new_len, value)
}
pub fn resize_zero(&mut self, new_len: usize) -> Result<(), ()> {
self.bytes.resize_default(new_len)
}
pub unsafe fn set_len(&mut self, new_len: usize) {
self.bytes.set_len(new_len)
}
pub fn swap_remove(&mut self, index: usize) -> u8 {
self.bytes.swap_remove(index)
}
pub unsafe fn swap_remove_unchecked(&mut self, index: usize) -> u8 {
unsafe { self.bytes.swap_remove_unchecked(index) }
}
pub fn is_full(&self) -> bool {
self.bytes.is_full()
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
pub fn starts_with(&self, needle: &[u8]) -> bool {
self.bytes.starts_with(needle)
}
pub fn ends_with(&self, needle: &[u8]) -> bool {
self.bytes.ends_with(needle)
}
pub fn insert(&mut self, index: usize, value: u8) -> Result<(), ()> {
self.bytes.insert(index, value).map_err(drop)
}
pub fn remove(&mut self, index: usize) -> u8 {
self.bytes.remove(index)
}
pub fn retain(&mut self, f: impl FnMut(&u8) -> bool) {
self.bytes.retain(f)
}
pub fn retain_mut(&mut self, f: impl FnMut(&mut u8) -> bool) {
self.bytes.retain_mut(f)
}
}
impl<const N: usize> Bytes<N> {
// /// Some APIs offer an interface of the form `f(&mut [u8]) -> Result<usize, E>`,
// /// with the contract that the Ok-value signals how many bytes were written.
// ///
// /// This constructor allows wrapping such interfaces in a more ergonomic way,
// /// returning a Bytes willed using `f`.
// ///
// /// It seems it's not possible to do this as an actual `TryFrom` implementation.
// pub fn from_constructor<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.resize_default(count)
// .expect("Contructor returned size larger than capacity");
// data
// })
// }
@@ -136,32 +201,32 @@ impl<const N: usize> Bytes<N> {
Ok(())
}
pub fn insert(&mut self, index: usize, item: u8) -> Result<(), u8> {
self.insert_slice_at(&[item], index).map_err(|_| item)
}
// 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 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 {
// the place we are taking from.
let p = self.bytes.as_mut_ptr().add(index);
// pub(crate) unsafe fn remove_unchecked(&mut self, index: usize) -> u8 {
// // the place we are taking from.
// let p = self.bytes.as_mut_ptr().add(index);
// copy it out, unsafely having a copy of the value on
// the stack and in the vector at the same time.
let ret = ptr::read(p);
// // copy it out, unsafely having a copy of the value on
// // the stack and in the vector at the same time.
// let ret = ptr::read(p);
// shift everything down to fill in that spot.
ptr::copy(p.offset(1), p, self.len() - index - 1);
// // shift everything down to fill in that spot.
// ptr::copy(p.offset(1), p, self.len() - index - 1);
self.resize_default(self.len() - 1).unwrap();
ret
}
// 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)
@@ -171,6 +236,13 @@ impl<const N: usize> Bytes<N> {
self.bytes.resize_default(self.bytes.capacity()).ok();
}
/// Low-noise conversion between lengths.
///
/// For an infaillible version when `M` is known to be larger than `N`, see [`increase_capacity`](Self::increase_capacity)
pub fn resize_capacity<const M: usize>(&self) -> Result<Bytes<M>, ()> {
Bytes::try_from(&**self)
}
/// Copy the contents of this `Bytes` instance into a new instance with a higher capacity.
///
/// ```
@@ -194,33 +266,6 @@ impl<const N: usize> Bytes<N> {
bytes.extend_from_slice(self.as_slice()).unwrap();
bytes.into()
}
/// Fallible conversion into differently sized byte buffer.
pub fn to_bytes<const M: usize>(&self) -> Result<Bytes<M>, ()> {
Bytes::<M>::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).unwrap();
let buffer = vec.deref_mut();
let writer = serde_cbor::ser::SliceWrite::new(buffer);
let mut ser = serde_cbor::Serializer::new(writer)
.packed_format()
// .pack_starting_with(1)
// .pack_to_depth(1)
;
t.serialize(&mut ser).unwrap();
let writer = ser.into_inner();
let size = writer.bytes_written();
vec.resize_default(size).unwrap();
Self::from(vec)
}
}
/// Construct a `Bytes<N>` instance from an array with `N` elements.
@@ -324,7 +369,7 @@ impl<const N: usize> AsMut<[u8]> for Bytes<N> {
}
impl<const N: usize> Deref for Bytes<N> {
type Target = Vec<u8, N>;
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.bytes
@@ -337,18 +382,6 @@ impl<const N: usize> DerefMut for Bytes<N> {
}
}
// impl Borrow<Bytes> for Bytes<N> {
// fn borrow(&self) -> &Bytes {
// Bytes::new(&self.bytes)
// }
// }
// impl BorrowMut<Bytes> for Bytes<N> {
// fn borrow_mut(&mut self) -> &mut Bytes {
// unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
// }
// }
impl<Rhs, const N: usize> PartialEq<Rhs> for Bytes<N>
where
Rhs: ?Sized + AsRef<[u8]>,
@@ -409,7 +442,18 @@ impl<const N: usize> Serialize for Bytes<N> {
}
}
// TODO: can we delegate to Vec<u8, N> deserialization instead of reimplementing?
impl<const N: usize> core::fmt::Write for Bytes<N> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.bytes.write_str(s)
}
fn write_char(&mut self, s: char) -> fmt::Result {
self.bytes.write_char(s)
}
fn write_fmt(&mut self, s: core::fmt::Arguments<'_>) -> fmt::Result {
self.bytes.write_fmt(s)
}
}
impl<'de, const N: usize> Deserialize<'de> for Bytes<N> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -445,6 +489,20 @@ impl<'de, const N: usize> Deserialize<'de> for Bytes<N> {
}
Ok(Bytes::<N>::from(buf))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
use serde::de::Error;
let mut this = Bytes::new();
while let Some(byte) = seq.next_element()? {
this.push(byte)
.map_err(|()| A::Error::invalid_length(this.len(), &self))?;
}
Ok(this)
}
}
deserializer.deserialize_bytes(ValueVisitor)
@@ -466,9 +524,9 @@ mod tests_serde {
bytes.push(1).unwrap();
assert_tokens(&bytes, &[Token::Bytes(&[1])]);
assert!(bytes.extend_from_slice(&[2; 16]).is_err());
assert_eq!(&**bytes, &[1]);
assert_eq!(&*bytes, &[1]);
assert!(bytes.extend_from_slice(&[2; 15]).is_ok());
assert_eq!(&**bytes, &[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]);
assert_eq!(&*bytes, &[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]);
assert_tokens(
&bytes,
&[Token::Bytes(&[
@@ -481,7 +539,10 @@ mod tests_serde {
fn display() {
assert_eq!(
r"b'\x00abcde\n'",
format!("{:?}", Bytes::<10>::from_slice(b"\0abcde\n").unwrap())
format!(
"{:?}",
Bytes::<10>::try_from(b"\0abcde\n".as_slice()).unwrap()
)
);
}
}