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