mirror of
https://github.com/trussed-dev/heapless-bytes.git
synced 2026-06-20 04:16:33 -07:00
Some ergonomics improvements
This commit is contained in:
@@ -10,6 +10,10 @@ repository = "https://github.com/ycrypto/heapless-bytes"
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ufmt = "0.1.0"
|
||||
typenum = "1.11.2"
|
||||
|
||||
[dependencies.heapless]
|
||||
version = "0.5.1"
|
||||
default-features = false
|
||||
|
||||
+92
-1
@@ -14,6 +14,10 @@ use core::{
|
||||
|
||||
pub use heapless::consts;
|
||||
pub use heapless::ArrayLength;
|
||||
// bring trait in scope to use `consts::Uxx::USIZE` etc.,
|
||||
// to get the corresponding size of Bytes.
|
||||
pub use typenum::Unsigned;
|
||||
|
||||
use heapless::Vec;
|
||||
|
||||
use serde::{
|
||||
@@ -26,6 +30,17 @@ 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> {
|
||||
/// Construct a new, empty `Bytes<N>`.
|
||||
pub fn new() -> Self {
|
||||
@@ -49,6 +64,13 @@ impl<N: ArrayLength<u8>> Bytes<N> {
|
||||
self.bytes
|
||||
}
|
||||
|
||||
/// Low-noise conversion between lengths.
|
||||
///
|
||||
/// We can't implement TryInto since it would clash with blanket implementations.
|
||||
pub fn try_convert_into<M: ArrayLength<u8>>(&self) -> Result<Bytes<M>, ()> {
|
||||
Bytes::<M>::try_from_slice(self)
|
||||
}
|
||||
|
||||
// #[doc(hidden)]
|
||||
// pub fn into_iter(self) -> <Vec<u8, N> as IntoIterator>::IntoIter {
|
||||
// self.bytes.into_iter()
|
||||
@@ -60,6 +82,43 @@ impl<N: ArrayLength<u8>> Bytes<N> {
|
||||
Ok(Self::from(bytes))
|
||||
}
|
||||
|
||||
/// 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
|
||||
})
|
||||
}
|
||||
|
||||
// pub fn try_from<'a, E>(
|
||||
// f: impl FnOnce(&'a mut [u8]) -> core::result::Result<&'a mut [u8], 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
|
||||
// })
|
||||
// }
|
||||
|
||||
// cf. https://internals.rust-lang.org/t/add-vec-insert-slice-at-to-insert-the-content-of-a-slice-at-an-arbitrary-index/11008/3
|
||||
pub fn insert_slice_at(&mut self, slice: &[u8], at: usize) -> core::result::Result<(), ()> {
|
||||
let l = slice.len();
|
||||
@@ -83,7 +142,7 @@ impl<N: ArrayLength<u8>> Bytes<N> {
|
||||
}
|
||||
|
||||
pub fn resize_to_capacity(&mut self) {
|
||||
self.bytes.resize_default(self.bytes.len()).ok();
|
||||
self.bytes.resize_default(self.bytes.capacity()).ok();
|
||||
}
|
||||
|
||||
// pub fn deref_mut(&mut self) -> &mut [u8] {
|
||||
@@ -113,6 +172,26 @@ impl<N: ArrayLength<u8>> Bytes<N> {
|
||||
}
|
||||
}
|
||||
|
||||
// impl<N, E, F> TryFrom<F> for Bytes<N>
|
||||
// where
|
||||
// N: ArrayLength<u8>,
|
||||
// F: FnOnce(&mut [u8]) -> Result<usize, E>,
|
||||
// {
|
||||
// type Error = E;
|
||||
|
||||
// fn try_from(f: F) -> Result<Self, Self::Error> {
|
||||
|
||||
// let mut data = Self::new();
|
||||
// data.resize_to_capacity();
|
||||
// let result = f(&mut data);
|
||||
|
||||
// result.map(|count| {
|
||||
// data.resize_default(count).unwrap();
|
||||
// data
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<N: ArrayLength<u8>> Debug for Bytes<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// TODO: There has to be a better way :'-)
|
||||
@@ -131,6 +210,18 @@ impl<N: ArrayLength<u8>> Debug for Bytes<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> ufmt::uDebug for Bytes<N>
|
||||
where
|
||||
N: ArrayLength<u8>,
|
||||
{
|
||||
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
|
||||
where
|
||||
W: ufmt::uWrite + ?Sized,
|
||||
{
|
||||
<[u8] as ufmt::uDebug>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: ArrayLength<u8>> AsRef<[u8]> for Bytes<N> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.bytes
|
||||
|
||||
Reference in New Issue
Block a user