1use alloc::rc::Rc;
7use alloc::sync::Arc;
8use alloc::vec::Vec;
9
10use bytes::{Buf, Bytes};
11use smallvec::{SmallVec, smallvec};
12use thiserror::Error;
13
14use super::access::MemOps;
15
16#[derive(Debug, Error, Copy, Clone)]
17pub enum AllocError {
18 #[error("Invalid region addr {0}")]
19 InvalidAlign(u64),
20 #[error("Invalid free addr {0} and size {1}")]
21 InvalidFree(u64, usize),
22 #[error("Invalid argument")]
23 InvalidArg,
24 #[error("Empty region")]
25 EmptyRegion,
26 #[error("No space available")]
27 NoSpace,
28 #[error("Requested size exceeds pool capacity")]
29 OutOfMemory,
30 #[error("Overflow")]
31 Overflow,
32}
33
34#[derive(Debug, Clone, Copy)]
36pub struct Allocation {
37 pub addr: u64,
39 pub len: usize,
41}
42
43pub trait BufferProvider {
45 fn max_alloc_len(&self) -> usize {
47 usize::MAX
48 }
49
50 fn alloc(&self, len: usize) -> Result<Allocation, AllocError>;
52
53 fn dealloc(&self, addr: u64) -> Result<(), AllocError>;
55
56 fn reset(&self) {}
58
59 fn alloc_sg(&self, total_len: usize) -> Result<SmallVec<[Allocation; 4]>, AllocError> {
61 if total_len == 0 {
62 return Err(AllocError::InvalidArg);
63 }
64
65 let seg_cap = self.max_alloc_len();
66 if seg_cap == 0 {
67 return Err(AllocError::InvalidArg);
68 }
69
70 let mut rem = total_len;
71 let mut sgs = SmallVec::<[Allocation; 4]>::new();
72
73 while rem > 0 {
74 let len = rem.min(seg_cap);
75 match self.alloc(len) {
76 Ok(alloc) => {
77 sgs.push(alloc);
78 rem -= len;
79 }
80 Err(err) => {
81 for sg in sgs {
82 let _res = self.dealloc(sg.addr);
83 debug_assert!(_res.is_ok(), "dealloc failed: {_res:?}");
84 }
85 return Err(err);
86 }
87 }
88 }
89
90 Ok(sgs)
91 }
92}
93
94impl<T: BufferProvider> BufferProvider for Rc<T> {
95 fn max_alloc_len(&self) -> usize {
96 (**self).max_alloc_len()
97 }
98 fn alloc(&self, len: usize) -> Result<Allocation, AllocError> {
99 (**self).alloc(len)
100 }
101 fn dealloc(&self, addr: u64) -> Result<(), AllocError> {
102 (**self).dealloc(addr)
103 }
104 fn reset(&self) {
105 (**self).reset()
106 }
107 fn alloc_sg(&self, total_len: usize) -> Result<SmallVec<[Allocation; 4]>, AllocError> {
108 (**self).alloc_sg(total_len)
109 }
110}
111
112impl<T: BufferProvider> BufferProvider for Arc<T> {
113 fn max_alloc_len(&self) -> usize {
114 (**self).max_alloc_len()
115 }
116 fn alloc(&self, len: usize) -> Result<Allocation, AllocError> {
117 (**self).alloc(len)
118 }
119 fn dealloc(&self, addr: u64) -> Result<(), AllocError> {
120 (**self).dealloc(addr)
121 }
122 fn reset(&self) {
123 (**self).reset()
124 }
125 fn alloc_sg(&self, total_len: usize) -> Result<SmallVec<[Allocation; 4]>, AllocError> {
126 (**self).alloc_sg(total_len)
127 }
128}
129
130#[derive(Debug, Clone, Default)]
135pub struct Segments(SmallVec<[Bytes; 4]>);
136
137impl Segments {
138 pub fn new(segments: impl IntoIterator<Item = Bytes>) -> Self {
140 Self(segments.into_iter().collect())
141 }
142
143 pub fn single(segment: Bytes) -> Self {
145 Self(smallvec![segment])
146 }
147
148 pub(crate) fn from_smallvec(segments: SmallVec<[Bytes; 4]>) -> Self {
149 Self(segments)
150 }
151
152 pub fn len(&self) -> usize {
154 self.0.iter().map(Bytes::len).sum()
155 }
156
157 pub fn is_empty(&self) -> bool {
159 self.len() == 0
160 }
161
162 pub fn segment_count(&self) -> usize {
164 self.0.len()
165 }
166
167 pub fn as_slice(&self) -> &[Bytes] {
169 &self.0
170 }
171
172 pub fn iter(&self) -> impl Iterator<Item = &Bytes> {
174 self.0.iter()
175 }
176
177 pub fn as_buf(&self) -> SegmentsBuf<'_> {
179 SegmentsBuf::new(&self.0, self.len())
180 }
181
182 pub fn to_bytes(&self) -> Bytes {
187 match self.0.as_slice() {
188 [] => Bytes::new(),
189 [segment] => segment.clone(),
190 _ => self.collect(&self.0, self.len()),
191 }
192 }
193
194 pub fn into_bytes(mut self) -> Bytes {
199 match self.0.len() {
200 0 => Bytes::new(),
201 1 => self.0.pop().unwrap_or_default(),
202 _ => self.collect(&self.0, self.len()),
203 }
204 }
205
206 fn collect(&self, sgs: &[Bytes], len: usize) -> Bytes {
207 let mut out = Vec::with_capacity(len);
208 out.extend(sgs.iter().flat_map(|seg| seg.iter().copied()));
209 Bytes::from(out)
210 }
211}
212
213#[derive(Debug, Clone)]
217pub struct SegmentsBuf<'a> {
218 segments: &'a [Bytes],
219 index: usize,
220 offset: usize,
221 remaining: usize,
222}
223
224impl<'a> SegmentsBuf<'a> {
225 fn new(segments: &'a [Bytes], len: usize) -> Self {
226 let mut this = Self {
227 segments,
228 index: 0,
229 offset: 0,
230 remaining: len,
231 };
232
233 this.skip_empty_segments();
234 this
235 }
236
237 fn skip_empty_segments(&mut self) {
238 while self.index < self.segments.len() && self.offset >= self.segments[self.index].len() {
239 self.index += 1;
240 self.offset = 0;
241 }
242 }
243}
244
245impl Buf for SegmentsBuf<'_> {
246 fn remaining(&self) -> usize {
247 self.remaining
248 }
249
250 fn chunk(&self) -> &[u8] {
251 if self.remaining == 0 {
252 return &[];
253 }
254
255 let segment = self.segments[self.index].as_ref();
256 &segment[self.offset..]
257 }
258
259 fn advance(&mut self, cnt: usize) {
260 assert!(cnt <= self.remaining, "cannot advance past remaining bytes");
261
262 self.remaining -= cnt;
263 let mut cnt = cnt;
264
265 while cnt > 0 {
266 let seg_rem = self.segments[self.index].len() - self.offset;
267 let n = seg_rem.min(cnt);
268 self.offset += n;
269 cnt -= n;
270 self.skip_empty_segments();
271 }
272
273 if self.remaining == 0 {
274 self.index = self.segments.len();
275 self.offset = 0;
276 }
277 }
278}
279
280#[derive(Debug)]
289pub struct BufferOwner<P: BufferProvider, M: MemOps> {
290 pub(crate) mem: M,
291 pub(crate) alloc: OwnedAlloc<P>,
292 pub(crate) written: usize,
293}
294
295impl<P: BufferProvider, M: MemOps> AsRef<[u8]> for BufferOwner<P, M> {
296 fn as_ref(&self) -> &[u8] {
297 let alloc = self.alloc.allocation();
298 let len = self.written.min(alloc.len);
299 match unsafe { self.mem.as_slice(alloc.addr, len) } {
302 Ok(slice) => slice,
303 Err(_) => {
304 debug_assert!(false, "BufferOwner direct slice failed");
305 &[]
306 }
307 }
308 }
309}
310
311#[derive(Debug)]
316pub struct OwnedAlloc<P: BufferProvider> {
317 inner: Option<Inner<P>>,
318}
319
320#[derive(Debug)]
321struct Inner<P: BufferProvider> {
322 pool: P,
323 alloc: Allocation,
324}
325
326impl<P: BufferProvider> OwnedAlloc<P> {
327 pub fn new(pool: P, alloc: Allocation) -> Self {
329 Self {
330 inner: Some(Inner { pool, alloc }),
331 }
332 }
333
334 pub fn allocate(pool: P, len: usize) -> Result<Self, AllocError> {
336 let alloc = pool.alloc(len)?;
337 Ok(Self::new(pool, alloc))
338 }
339
340 #[allow(clippy::expect_used)]
345 pub fn allocation(&self) -> Allocation {
346 self.inner
347 .as_ref()
348 .map(|inner| inner.alloc)
349 .expect("OwnedAlloc::allocation called after ownership transfer")
350 }
351
352 #[allow(clippy::expect_used)]
356 pub fn into_raw(mut self) -> Allocation {
357 self.inner
358 .take()
359 .map(|inner| inner.alloc)
360 .expect("OwnedAlloc::into_raw called after ownership transfer")
361 }
362}
363
364impl<P: BufferProvider> Drop for OwnedAlloc<P> {
365 fn drop(&mut self) {
366 if let Some(Inner { pool, alloc }) = self.inner.take() {
367 let result = pool.dealloc(alloc.addr);
368 debug_assert!(result.is_ok(), "OwnedAlloc drop dealloc failed: {result:?}");
369 }
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 use bytes::Buf;
376
377 use super::*;
378
379 #[test]
380 fn segments_cursor_advances_across_segments() {
381 let segments = Segments::new([
382 Bytes::from_static(b"abc"),
383 Bytes::from_static(b"def"),
384 Bytes::from_static(b"ghi"),
385 ]);
386 let mut cursor = segments.as_buf();
387
388 assert_eq!(cursor.remaining(), 9);
389 assert_eq!(cursor.chunk(), b"abc");
390
391 cursor.advance(2);
392 assert_eq!(cursor.remaining(), 7);
393 assert_eq!(cursor.chunk(), b"c");
394
395 cursor.advance(1);
396 assert_eq!(cursor.chunk(), b"def");
397
398 cursor.advance(4);
399 assert_eq!(cursor.chunk(), b"hi");
400
401 cursor.advance(2);
402 assert_eq!(cursor.remaining(), 0);
403 assert_eq!(cursor.chunk(), b"");
404 }
405
406 #[test]
407 fn segments_cursor_skips_empty_segments() {
408 let segments = Segments::new([
409 Bytes::new(),
410 Bytes::from_static(b"ab"),
411 Bytes::new(),
412 Bytes::from_static(b"cd"),
413 Bytes::new(),
414 ]);
415 let mut cursor = segments.as_buf();
416
417 assert_eq!(cursor.remaining(), 4);
418 assert_eq!(cursor.chunk(), b"ab");
419
420 cursor.advance(2);
421 assert_eq!(cursor.remaining(), 2);
422 assert_eq!(cursor.chunk(), b"cd");
423
424 cursor.advance(2);
425 assert!(!cursor.has_remaining());
426 assert_eq!(cursor.chunk(), b"");
427 }
428
429 #[test]
430 fn segments_cursor_reads_split_header_without_collecting_all_segments() {
431 let segments = Segments::new([
432 Bytes::from_static(&[0x01, 0x02, 0x03]),
433 Bytes::from_static(&[0x04, 0x05]),
434 Bytes::from_static(&[0x06, 0x07, 0x08, 0xff]),
435 ]);
436 let mut cursor = segments.as_buf();
437 let mut header = [0u8; 8];
438
439 cursor.try_copy_to_slice(&mut header).unwrap();
440
441 assert_eq!(header, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]);
442 assert_eq!(cursor.remaining(), 1);
443 assert_eq!(cursor.chunk(), &[0xff]);
444 }
445
446 #[test]
447 fn segments_cursor_copy_to_bytes_collects_only_requested_prefix() {
448 let segments = Segments::new([
449 Bytes::from_static(b"hello"),
450 Bytes::from_static(b" "),
451 Bytes::from_static(b"world"),
452 ]);
453 let mut cursor = segments.as_buf();
454
455 let prefix = cursor.copy_to_bytes(6);
456
457 assert_eq!(prefix.as_ref(), b"hello ");
458 assert_eq!(cursor.remaining(), 5);
459 assert_eq!(cursor.chunk(), b"world");
460 }
461
462 #[test]
463 fn segments_into_bytes_reuses_single_segment() {
464 let segment = Bytes::from(vec![1, 2, 3, 4]);
465 let ptr = segment.as_ptr();
466
467 let collected = Segments::single(segment).into_bytes();
468
469 assert_eq!(collected.as_ptr(), ptr);
470 assert_eq!(collected.as_ref(), &[1, 2, 3, 4]);
471 }
472}