diff --git a/Cargo.toml b/Cargo.toml index 56c7b8d..e4e517d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,9 @@ edition = "2021" heapless = { version = "0.8", default-features = false } serde = { version = "1.0", default-features = false } -[dependencies.serde_cbor] -version = "0.11.0" -default-features = false -optional = true - -[features] -cbor = ["serde_cbor"] - [dev-dependencies] serde_test = "1.0.176" + +[features] +# From/Into implementation to `heapless::Vec` +"heapless-0.8" = [] diff --git a/src/lib.rs b/src/lib.rs index 6b5845d..30201c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { bytes: Vec, } @@ -30,147 +29,270 @@ pub type Bytes16 = Bytes<16>; pub type Bytes32 = Bytes<32>; pub type Bytes64 = Bytes<64>; -impl From> for Bytes { - fn from(vec: Vec) -> Self { - Self { bytes: vec } +#[cfg(feature = "heapless-0.8")] +impl From> for Bytes { + fn from(vec: Vec) -> Self { + Bytes { bytes: vec }.increase_capacity() + } +} + +#[cfg(feature = "heapless-0.8")] +impl From> for Vec { + fn from(value: Bytes) -> Self { + value.increase_capacity().bytes + } +} + +impl TryFrom<&[u8]> for Bytes { + type Error = (); + fn try_from(value: &[u8]) -> Result { + Ok(Self { + bytes: Vec::from_slice(value)?, + }) } } impl Bytes { /// Construct a new, empty `Bytes`. pub fn new() -> Self { - Bytes::from(Vec::new()) + Self { bytes: Vec::new() } } - /// Unwraps the Vec, same as `into_vec`. - pub fn into_inner(self) -> Vec { - self.bytes + pub fn as_ptr(&self) -> *const u8 { + self.bytes.as_ptr() } - /// Unwraps the Vec, same as `into_inner`. - pub fn into_vec(self) -> Vec { - self.bytes + /// Returns a raw pointer to the vector’s buffer, which may be mutated through + 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. + /// Extracts a slice containing the entire buffer. 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. + /// Extracts a mutable slice containing the entire buffer. pub fn as_mut_slice(&mut self) -> &mut [u8] { - self.bytes.as_mut() + self.bytes.as_mut_slice() } - /// Low-noise conversion between lengths. + /// Get the capacity of the buffer. /// - /// We can't implement TryInto since it would clash with blanket implementations. - pub fn try_convert_into(&self) -> Result, ()> { - Bytes::::from_slice(self) + /// Always equal to the `N` const generic. + pub const fn capacity(&self) -> usize { + self.bytes.capacity() } - // pub fn try_from_slice(slice: &[u8]) -> core::result::Result { - // let mut bytes = Vec::::new(); - // bytes.extend_from_slice(slice)?; - // Ok(Self::from(bytes)) - // } - - pub fn from_slice(slice: &[u8]) -> core::result::Result { - let mut bytes = Vec::::new(); - bytes.extend_from_slice(slice)?; - Ok(Self::from(bytes)) + /// Clear the buffer, making it empty + pub fn clear(&mut self) { + self.bytes.clear() } - /// Some APIs offer an interface of the form `f(&mut [u8]) -> Result`, - /// with the contract that the Ok-value signals how many bytes were written. + /// Extends the buffer from an iterator. /// - /// This constructor allows wrapping such interfaces in a more ergonomic way, - /// returning a Bytes willed using `f`. + /// # Panic /// - /// It seems it's not possible to do this as an actual `TryFrom` implementation. - pub fn try_from( - f: impl FnOnce(&mut [u8]) -> core::result::Result, - ) -> core::result::Result { - let mut data = Self::new(); - data.resize_to_capacity(); - let result = f(&mut data); + /// Panics if the buffer cannot hold all elements of the iterator. + #[deprecated( + since = "0.4.0", + note = "Panics when out of capacity, use try_extend instead" + )] + pub fn extend>(&mut self, iter: I) { + self.bytes.extend(iter) + } - result.map(|count| { - data.resize_default(count).unwrap(); - data - }) + /// Extends the buffer from an iterator. + /// + /// Returns [`Err`] if out of capacity + pub fn try_extend>(&mut self, iter: I) -> Result<(), ()> { + for b in iter { + self.push(b)?; + } + Ok(()) } - // pub fn try_from<'a, E>( - // f: impl FnOnce(&'a mut [u8]) -> core::result::Result<&'a mut [u8], E> - // ) - // -> core::result::Result - // { - // let mut data = Self::new(); - // data.resize_to_capacity(); - // let result = f(&mut data); + /// Extend the buffer with the contents of a slice + pub fn extend_from_slice(&mut self, other: &[u8]) -> Result<(), ()> { + self.bytes.extend_from_slice(other) + } - // result.map(|count| { - // data.resize_default(count).unwrap(); - // data - // }) - // } + /// Removes the last byte from the buffer and returns it, or `None` if it's empty + pub fn pop(&mut self) -> Option { + self.bytes.pop() + } - // 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(); - let before = self.len(); + /// Appends a byte to the back of the collection + pub fn push(&mut self, byte: u8) -> Result<(), ()> { + self.bytes.push(byte).map_err(drop) + } - // make space - self.bytes.resize_default(before + l)?; + /// Removes the last byte from the buffer and returns it + /// + /// # Safety + /// + /// This assumes the buffer to have at least one element. + pub unsafe fn pop_unchecked(&mut self) -> u8 { + unsafe { self.bytes.pop_unchecked() } + } - // move back existing - let raw: &mut [u8] = &mut self.bytes; - raw.copy_within(at..before, at + l); + /// Appends a byte to the back of the buffer + /// + /// # Safety + /// + /// This assumes the buffer is not full. + pub unsafe fn push_unchecked(&mut self, byte: u8) { + unsafe { + self.bytes.push_unchecked(byte); + } + } - // insert slice - raw[at..][..l].copy_from_slice(slice); + /// Shortens the buffer, keeping the first `len` elements and dropping the rest. + pub fn truncate(&mut self, len: usize) { + self.bytes.truncate(len) + } - Ok(()) + /// Resizes the buffer in-place so that len is equal to new_len. + /// + /// If new_len is greater than len, the buffer is extended by the + /// difference, with each additional slot filled with `value`. If + /// `new_len` is less than `len`, the buffer is simply truncated. + /// + /// See also [`resize_zero`](Self::resize_zero). + pub fn resize(&mut self, new_len: usize, value: u8) -> Result<(), ()> { + self.bytes.resize(new_len, value) } - pub fn insert(&mut self, index: usize, item: u8) -> Result<(), u8> { - self.insert_slice_at(&[item], index).map_err(|_| item) + /// Resizes the buffer in-place so that len is equal to new_len. + /// + /// If new_len is greater than len, the buffer is extended by the + /// difference, with each additional slot filled with `0`. If + /// `new_len` is less than `len`, the buffer is simply truncated. + pub fn resize_zero(&mut self, new_len: usize) -> Result<(), ()> { + self.bytes.resize_default(new_len) } - pub fn remove(&mut self, index: usize) -> Result { - if index < self.len() { - unsafe { Ok(self.remove_unchecked(index)) } - } else { - Err(()) - } + /// Forces the length of the buffer to `new_len`. + /// + /// This is a low-level operation that maintains none of the normal + /// invariants of the type. Normally changing the length of a buffer + /// is done using one of the safe operations instead, such as + /// [`truncate`], [`resize`], [`extend`], or [`clear`]. + /// + /// [`truncate`]: Self::truncate + /// [`resize`]: Self::resize + /// [`extend`]: core::iter::Extend + /// [`clear`]: Self::clear + /// + /// # Safety + /// + /// - `new_len` must be less than or equal to [`capacity()`]. + /// - The elements at `old_len..new_len` must be initialized. + /// + /// [`capacity()`]: Self::capacity + /// + pub unsafe fn set_len(&mut self, new_len: usize) { + self.bytes.set_len(new_len) } - 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); + /// Removes a byte from the buffer and returns it. + /// + /// The removed byte is replaced by the last byte of the vector. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + pub fn swap_remove(&mut self, index: usize) -> u8 { + self.bytes.swap_remove(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); + /// Removes a byte from the buffer and returns it. + /// + /// The removed byte is replaced by the last byte of the vector. + /// + /// This does not preserve ordering, but is *O*(1). + /// + /// # Safety + /// + /// `index` must not be out of bounds. + pub unsafe fn swap_remove_unchecked(&mut self, index: usize) -> u8 { + unsafe { self.bytes.swap_remove_unchecked(index) } + } - // shift everything down to fill in that spot. - ptr::copy(p.offset(1), p, self.len() - index - 1); + /// Returns true if the buffer is full + pub fn is_full(&self) -> bool { + self.bytes.is_full() + } - self.resize_default(self.len() - 1).unwrap(); - ret + /// Returns true if the buffer is empty + pub fn is_empty(&self) -> bool { + self.bytes.is_empty() } - pub fn resize_default(&mut self, new_len: usize) -> core::result::Result<(), ()> { - self.bytes.resize_default(new_len) + /// Returns `true` if `needle` is a prefix of the buffer. + /// + /// Always returns `true` if `needle` is an empty slice. + pub fn starts_with(&self, needle: &[u8]) -> bool { + self.bytes.starts_with(needle) + } + + /// Returns `true` if `needle` is a suffix of the buffer. + /// + /// Always returns `true` if `needle` is an empty slice. + pub fn ends_with(&self, needle: &[u8]) -> bool { + self.bytes.ends_with(needle) + } + + /// Inserts a byte at position `index` within the buffer, shifting all + /// bytes after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + pub fn insert(&mut self, index: usize, value: u8) -> Result<(), ()> { + self.bytes.insert(index, value).map_err(drop) + } + + /// Removes and return the byte at position `index` within the buffer, shifting all + /// bytes after it to the left. + /// + /// # Panics + /// + /// Panics if `index > len`. + pub fn remove(&mut self, index: usize) -> u8 { + self.bytes.remove(index) + } + + /// Retains only the bytes specified by the predicate. + /// + /// In other words, remove all bytes `b` for which `f(&b)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + pub fn retain(&mut self, f: impl FnMut(&u8) -> bool) { + self.bytes.retain(f) + } + /// Retains only the bytes specified by the predicate, passing a mutable reference to it. + /// + /// In other words, remove all bytes `b` for which `f(&mut b)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + pub fn retain_mut(&mut self, f: impl FnMut(&mut u8) -> bool) { + self.bytes.retain_mut(f) } pub fn resize_to_capacity(&mut self) { 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(&self) -> Result, ()> { + Bytes::try_from(&**self) + } + /// Copy the contents of this `Bytes` instance into a new instance with a higher capacity. /// /// ``` @@ -192,34 +314,7 @@ impl Bytes { let mut bytes = Vec::new(); // bytes has length 0 and capacity M, self has length N, N <= M, so this can never panic bytes.extend_from_slice(self.as_slice()).unwrap(); - bytes.into() - } - - /// Fallible conversion into differently sized byte buffer. - pub fn to_bytes(&self) -> Result, ()> { - Bytes::::from_slice(self) - } - - #[cfg(feature = "cbor")] - pub fn from_serialized(t: &T) -> Self - where - T: Serialize, - { - let mut vec = Vec::::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) + Bytes { bytes } } } @@ -268,12 +363,12 @@ impl AssertLessThanEq { /// let bytes: Bytes<3> = Bytes::from(&[0, 1, 2, 3]); // does not compile /// ``` impl From<&[u8; M]> for Bytes { - fn from(bytes: &[u8; M]) -> Self { + fn from(data: &[u8; M]) -> Self { let () = AssertLessThanEq::::ASSERT; - let mut vec = Vec::new(); + let mut bytes = Vec::new(); // vec has length 0 and capacity N, bytes has length M, M <= N, so this can never panic - vec.extend_from_slice(bytes).unwrap(); - vec.into() + bytes.extend_from_slice(data).unwrap(); + Bytes { bytes } } } @@ -324,7 +419,7 @@ impl AsMut<[u8]> for Bytes { } impl Deref for Bytes { - type Target = Vec; + type Target = [u8]; fn deref(&self) -> &Self::Target { &self.bytes @@ -337,18 +432,6 @@ impl DerefMut for Bytes { } } -// impl Borrow for Bytes { -// fn borrow(&self) -> &Bytes { -// Bytes::new(&self.bytes) -// } -// } - -// impl BorrowMut for Bytes { -// fn borrow_mut(&mut self) -> &mut Bytes { -// unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) } -// } -// } - impl PartialEq for Bytes where Rhs: ?Sized + AsRef<[u8]>, @@ -373,12 +456,26 @@ impl Hash for Bytes { } } +#[derive(Clone)] +pub struct IntoIter { + inner: as IntoIterator>::IntoIter, +} + +impl Iterator for IntoIter { + type Item = u8; + fn next(&mut self) -> Option { + self.inner.next() + } +} + impl IntoIterator for Bytes { type Item = u8; - type IntoIter = as IntoIterator>::IntoIter; + type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { - self.bytes.into_iter() + IntoIter { + inner: self.bytes.into_iter(), + } } } @@ -409,7 +506,18 @@ impl Serialize for Bytes { } } -// TODO: can we delegate to Vec deserialization instead of reimplementing? +impl core::fmt::Write for Bytes { + 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 { fn deserialize(deserializer: D) -> Result where @@ -421,29 +529,28 @@ impl<'de, const N: usize> Deserialize<'de> for Bytes { type Value = Bytes; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") + formatter.write_str("a sequence of bytes") } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { - if v.len() > N { - // hprintln!("error! own size: {}, data size: {}", N::to_usize(), v.len()).ok(); - // return Err(E::invalid_length(values.capacity() + 1, &self))?; - return Err(E::invalid_length(v.len(), &self))?; - } - let mut buf: Vec = Vec::new(); - // avoid unwrapping even though redundant - match buf.extend_from_slice(v) { - Ok(()) => {} - Err(()) => { - // hprintln!("error! own size: {}, data size: {}", N::to_usize(), v.len()).ok(); - // return Err(E::invalid_length(values.capacity() + 1, &self))?; - return Err(E::invalid_length(v.len(), &self))?; - } + Bytes::try_from(v).map_err(|()| E::invalid_length(v.len(), &self)) + } + + fn visit_seq(self, mut seq: A) -> Result + 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(Bytes::::from(buf)) + Ok(this) } } @@ -452,7 +559,7 @@ impl<'de, const N: usize> Deserialize<'de> for Bytes { } #[cfg(test)] -mod tests_serde { +mod tests { use super::*; use serde_test::{assert_tokens, Token}; @@ -466,9 +573,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,25 +588,20 @@ 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() + ) ); } -} - -#[cfg(test)] -#[cfg(feature = "cbor")] -mod tests { - use super::*; #[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<17> = serde_cbor::de::from_mut_slice(&mut minimal).unwrap(); - - assert_eq!(client_data_hash, b"1234567890ABCDEF"); + fn from() { + let _: Bytes<10> = [0; 10].into(); + let _: Bytes<10> = (&[0; 8]).into(); + #[cfg(feature = "heapless-0.8")] + let _: Bytes<10> = Vec::::new().into(); + #[cfg(feature = "heapless-0.8")] + let _: Bytes<10> = Vec::::new().into(); } }