Merge pull request #340 from xgroleau/feat/add-bytes-support

Add support for `Bytes`
This commit is contained in:
Markus Reiter 2025-04-06 19:44:15 +00:00 committed by GitHub
commit b6c073923d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 114 additions and 0 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- Added `bytes::Buf` and `bytes::BufMut` implementations for `Vec`.
- Added `format` macro.
- Added `String::from_utf16`.
- Added `is_full`, `recent_index`, `oldest`, and `oldest_index` to `HistoryBuffer`

View File

@ -15,6 +15,8 @@ repository = "https://github.com/rust-embedded/heapless"
version = "0.8.0"
[features]
bytes = ["dep:bytes"]
# Enable polyfilling of atomics via `portable-atomic`.
# `portable-atomic` polyfills some functionality by default, but to get full atomics you must
# enable one of its features to tell it how to do it. See `portable-atomic` documentation for details.
@ -42,6 +44,7 @@ mpmc_large = []
nightly = []
[dependencies]
bytes = { version = "1", default-features = false, optional = true }
portable-atomic = { version = "1.0", optional = true }
hash32 = "0.3.0"
serde = { version = "1", optional = true, default-features = false }
@ -58,6 +61,7 @@ static_assertions = "1.1.0"
[package.metadata.docs.rs]
features = [
"bytes",
"ufmt",
"serde",
"defmt",

107
src/bytes.rs Normal file
View File

@ -0,0 +1,107 @@
//! Bytes implementations for heapless types
use crate::Vec;
use bytes::{buf::UninitSlice, Buf, BufMut};
unsafe impl<const N: usize> Buf for Vec<u8, N> {
#[inline]
fn remaining(&self) -> usize {
self.len()
}
#[inline]
fn chunk(&mut self) -> &[u8] {
self.as_slice()
}
#[inline]
unsafe fn advance(&mut self, cnt: usize) {
assert!(
cnt <= self.remaining(),
"cannot advance past `remaining`: {:?} <= {:?}",
cnt,
self.remaining(),
);
unsafe {
// SAFETY: We've checked that `cnt` <= `self.remaining()` and we know that
// `self.remaining()` <= `self.cap`.
self.advance_unchecked(cnt);
}
}
}
unsafe impl<const N: usize> BufMut for Vec<u8, N> {
#[inline]
fn remaining_mut(&self) -> usize {
N - self.len()
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let len = self.len();
let pos = len + cnt;
if pos >= N {
panic!("Advance out of range");
}
self.set_len(pos);
}
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
let len = self.len();
let ptr = self.as_mut_ptr();
unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, N)[len..] }
}
}
#[cfg(test)]
mod tests {
use crate::Vec;
use bytes::BufMut;
#[test]
#[should_panic]
fn buf_advance_out_of_bounds() {
let mut vec: Vec<u8, 8> = Vec::new();
vec.advance(9)
}
#[test]
fn buf_remaining() {
let mut vec: Vec<u8, 8> = Vec::new();
assert_eq!(vec.remaining(), 8);
vec.push(42).unwrap();
assert_eq!(vec.remaining(), 7);
}
#[test]
fn buf_chunk() {
let mut vec: Vec<u8, 8> = Vec::new();
assert_eq!(vec.chunk().len(), 8);
unsafe { vec.advance_mut(1) };
assert_eq!(vec.chunk().len(), 7);
}
#[test]
#[should_panic]
fn buf_mut_advance_mut_out_of_bounds() {
let mut vec: Vec<u8, 8> = Vec::new();
unsafe { vec.advance_mut(9) };
}
#[test]
fn buf_mut_remaining_mut() {
let mut vec: Vec<u8, 8> = Vec::new();
assert_eq!(vec.remaining_mut(), 8);
vec.push(42).unwrap();
assert_eq!(vec.remaining_mut(), 7);
}
#[test]
fn buf_mut_chunk_mut() {
let mut vec: Vec<u8, 8> = Vec::new();
assert_eq!(vec.chunk_mut().len(), 8);
unsafe { vec.advance_mut(1) };
assert_eq!(vec.chunk_mut().len(), 7);
}
}

View File

@ -192,6 +192,8 @@ mod de;
mod ser;
pub mod binary_heap;
#[cfg(feature = "bytes")]
mod bytes;
#[cfg(feature = "defmt")]
mod defmt;
#[cfg(any(