Skip to content

Commit b6c0739

Browse files
authored
Merge pull request #340 from xgroleau/feat/add-bytes-support
Add support for `Bytes`
2 parents 53a0f54 + 0b1e1a5 commit b6c0739

File tree

4 files changed

+114
-0
lines changed

4 files changed

+114
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Added
1111

12+
- Added `bytes::Buf` and `bytes::BufMut` implementations for `Vec`.
1213
- Added `format` macro.
1314
- Added `String::from_utf16`.
1415
- Added `is_full`, `recent_index`, `oldest`, and `oldest_index` to `HistoryBuffer`

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ repository = "https://github.com/rust-embedded/heapless"
1515
version = "0.8.0"
1616

1717
[features]
18+
bytes = ["dep:bytes"]
19+
1820
# Enable polyfilling of atomics via `portable-atomic`.
1921
# `portable-atomic` polyfills some functionality by default, but to get full atomics you must
2022
# enable one of its features to tell it how to do it. See `portable-atomic` documentation for details.
@@ -42,6 +44,7 @@ mpmc_large = []
4244
nightly = []
4345

4446
[dependencies]
47+
bytes = { version = "1", default-features = false, optional = true }
4548
portable-atomic = { version = "1.0", optional = true }
4649
hash32 = "0.3.0"
4750
serde = { version = "1", optional = true, default-features = false }
@@ -58,6 +61,7 @@ static_assertions = "1.1.0"
5861

5962
[package.metadata.docs.rs]
6063
features = [
64+
"bytes",
6165
"ufmt",
6266
"serde",
6367
"defmt",

src/bytes.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//! Bytes implementations for heapless types
2+
3+
use crate::Vec;
4+
use bytes::{buf::UninitSlice, Buf, BufMut};
5+
6+
unsafe impl<const N: usize> Buf for Vec<u8, N> {
7+
#[inline]
8+
fn remaining(&self) -> usize {
9+
self.len()
10+
}
11+
12+
#[inline]
13+
fn chunk(&mut self) -> &[u8] {
14+
self.as_slice()
15+
}
16+
17+
#[inline]
18+
unsafe fn advance(&mut self, cnt: usize) {
19+
assert!(
20+
cnt <= self.remaining(),
21+
"cannot advance past `remaining`: {:?} <= {:?}",
22+
cnt,
23+
self.remaining(),
24+
);
25+
unsafe {
26+
// SAFETY: We've checked that `cnt` <= `self.remaining()` and we know that
27+
// `self.remaining()` <= `self.cap`.
28+
self.advance_unchecked(cnt);
29+
}
30+
}
31+
}
32+
33+
unsafe impl<const N: usize> BufMut for Vec<u8, N> {
34+
#[inline]
35+
fn remaining_mut(&self) -> usize {
36+
N - self.len()
37+
}
38+
39+
#[inline]
40+
unsafe fn advance_mut(&mut self, cnt: usize) {
41+
let len = self.len();
42+
let pos = len + cnt;
43+
if pos >= N {
44+
panic!("Advance out of range");
45+
}
46+
self.set_len(pos);
47+
}
48+
49+
#[inline]
50+
fn chunk_mut(&mut self) -> &mut UninitSlice {
51+
let len = self.len();
52+
let ptr = self.as_mut_ptr();
53+
unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, N)[len..] }
54+
}
55+
}
56+
57+
#[cfg(test)]
58+
mod tests {
59+
use crate::Vec;
60+
use bytes::BufMut;
61+
62+
#[test]
63+
#[should_panic]
64+
fn buf_advance_out_of_bounds() {
65+
let mut vec: Vec<u8, 8> = Vec::new();
66+
vec.advance(9)
67+
}
68+
69+
#[test]
70+
fn buf_remaining() {
71+
let mut vec: Vec<u8, 8> = Vec::new();
72+
assert_eq!(vec.remaining(), 8);
73+
vec.push(42).unwrap();
74+
assert_eq!(vec.remaining(), 7);
75+
}
76+
77+
#[test]
78+
fn buf_chunk() {
79+
let mut vec: Vec<u8, 8> = Vec::new();
80+
assert_eq!(vec.chunk().len(), 8);
81+
unsafe { vec.advance_mut(1) };
82+
assert_eq!(vec.chunk().len(), 7);
83+
}
84+
85+
#[test]
86+
#[should_panic]
87+
fn buf_mut_advance_mut_out_of_bounds() {
88+
let mut vec: Vec<u8, 8> = Vec::new();
89+
unsafe { vec.advance_mut(9) };
90+
}
91+
92+
#[test]
93+
fn buf_mut_remaining_mut() {
94+
let mut vec: Vec<u8, 8> = Vec::new();
95+
assert_eq!(vec.remaining_mut(), 8);
96+
vec.push(42).unwrap();
97+
assert_eq!(vec.remaining_mut(), 7);
98+
}
99+
100+
#[test]
101+
fn buf_mut_chunk_mut() {
102+
let mut vec: Vec<u8, 8> = Vec::new();
103+
assert_eq!(vec.chunk_mut().len(), 8);
104+
unsafe { vec.advance_mut(1) };
105+
assert_eq!(vec.chunk_mut().len(), 7);
106+
}
107+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ mod de;
192192
mod ser;
193193

194194
pub mod binary_heap;
195+
#[cfg(feature = "bytes")]
196+
mod bytes;
195197
#[cfg(feature = "defmt")]
196198
mod defmt;
197199
#[cfg(any(

0 commit comments

Comments
 (0)