Skip to main content

storage_device/
buffer.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::buffer_allocator::BufferAllocator as PoolBufferAllocator;
6use std::borrow::Borrow;
7use std::marker::PhantomData;
8use std::ops::{Bound, Range, RangeBounds};
9use std::slice::SliceIndex;
10use storage_ptr_slice::{MutPtrByteSlice, PtrByteSlice};
11
12pub use crate::buffer_allocator::{BufferFuture, TryAllocateBuffer};
13
14#[cfg(target_os = "fuchsia")]
15use zx::sys::zx_paddr_t;
16
17/// An entity capable of reclaiming a memory buffer range when dropped.
18pub trait BufferAllocator: Send + Sync + std::fmt::Debug + 'static {
19    /// Frees or reclaims the specified memory range.
20    fn free_buffer(&self, range: Range<usize>);
21
22    /// Returns an identifier for this allocator based on its memory address.
23    fn identifier(&self) -> usize {
24        std::ptr::from_ref(self).addr()
25    }
26
27    /// Returns true if buffers produced by this allocator are trusted (unshared).
28    fn is_trusted(&self) -> bool {
29        false
30    }
31
32    /// Returns the underlying VMO if backed by a VMO and untrusted.
33    ///
34    /// If the allocator is trusted, this returns `None` to prevent external modification
35    /// of memory that is assumed to be unshared.
36    #[cfg(target_os = "fuchsia")]
37    fn vmo(&self) -> Option<Arc<zx::Vmo>> {
38        None
39    }
40
41    /// Returns the physical addresses for `range` if pinned, along with the contiguity.
42    #[cfg(target_os = "fuchsia")]
43    fn paddrs(&self, _range: &Range<usize>) -> Option<(&[zx_paddr_t], u64)> {
44        None
45    }
46}
47
48pub(super) fn round_down<T>(value: T, granularity: T) -> T
49where
50    T: num::Num + Copy,
51{
52    value - value % granularity
53}
54
55pub(super) fn round_up<T>(value: T, granularity: T) -> T
56where
57    T: num::Num + Copy,
58{
59    round_down(value + granularity - T::one(), granularity)
60}
61
62// Returns a range within a range.
63// For example, subrange(100..200, 20..30) = 120..130.
64fn subrange<R: RangeBounds<usize>>(source: &Range<usize>, bounds: &R) -> Range<usize> {
65    let subrange = (match bounds.start_bound() {
66        Bound::Included(&s) => source.start + s,
67        Bound::Excluded(&s) => source.start + s + 1,
68        Bound::Unbounded => source.start,
69    })..(match bounds.end_bound() {
70        Bound::Included(&e) => source.start + e + 1,
71        Bound::Excluded(&e) => source.start + e,
72        Bound::Unbounded => source.end,
73    });
74    assert!(subrange.end <= source.end);
75    subrange
76}
77
78fn split_range(range: &Range<usize>, mid: usize) -> (Range<usize>, Range<usize>) {
79    let l = range.end - range.start;
80    let base = range.start;
81    (base..base + mid, base + mid..base + l)
82}
83
84/// Buffer is a read-write buffer that can be used for I/O with the block device. They are created
85/// by a BufferAllocator, and automatically deallocate themselves when they go out of scope.
86///
87/// Most usage will be on the unowned BufferRef and MutableBufferRef types, since these types are
88/// used for Device::read and Device::write.
89///
90/// Buffers are always block-aligned (both in offset and length), but unaligned slices can be made
91/// with the reference types. That said, the Device trait requires aligned BufferRef and
92/// MutableBufferRef objects, so alignment must be restored by the time a device read/write is
93/// requested.
94///
95/// For example, when writing an unaligned amount of data to the device, generally two Buffers
96/// would need to be involved; the input Buffer could be used to write everything up to the last
97/// block, and a second single-block alignment Buffer would be used to read-modify-update the last
98/// block.
99use std::sync::Arc;
100
101#[derive(Debug)]
102pub struct BufferImpl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> {
103    slice: MutPtrByteSlice<'a>,
104    range: Range<usize>,
105    pub(super) allocator: H,
106    _phantom: PhantomData<fn() -> &'a A>,
107}
108
109pub type Buffer<'a> = BufferImpl<'a, &'a PoolBufferAllocator, PoolBufferAllocator>;
110pub type OwnedBuffer = BufferImpl<'static, Arc<dyn BufferAllocator>, dyn BufferAllocator>;
111
112// Alias for the traits which need to be satisfied for `subslice` and friends.
113// This trait is automatically satisfied for most typical uses (a..b, a.., ..b, ..).
114pub trait SliceRange: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
115impl<T> SliceRange for T where T: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
116
117impl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> BufferImpl<'a, H, A> {
118    pub(super) fn new(slice: MutPtrByteSlice<'a>, range: Range<usize>, allocator: H) -> Self {
119        assert_eq!(slice.len(), range.end - range.start);
120        Self { slice, range, allocator, _phantom: PhantomData }
121    }
122
123    /// Takes a read-only reference to this buffer.
124    pub fn as_ref(&self) -> BufferRef<'_> {
125        self.subslice(..)
126    }
127
128    /// Takes a read-only reference to this buffer over `range` (which must be within the size of
129    /// the buffer).
130    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
131        let new_range = subrange(&self.range, &range);
132        let relative_range =
133            (new_range.start - self.range.start)..(new_range.end - self.range.start);
134        let slice = self.slice.as_ptr_slice().subslice(relative_range);
135        BufferRef {
136            slice,
137            start: new_range.start,
138            end: new_range.end,
139            allocator_id: self.allocator.borrow().identifier(),
140            trusted: self.allocator.borrow().is_trusted(),
141        }
142    }
143
144    /// Takes a read-write reference to this buffer.
145    pub fn as_mut(&mut self) -> MutableBufferRef<'_> {
146        self.subslice_mut(..)
147    }
148
149    /// Returns an `io::Write` adapter for this buffer.
150    pub fn writer(&mut self) -> storage_ptr_slice::Writer<'_> {
151        self.slice.reborrow().writer()
152    }
153
154    /// Takes a read-write reference to this buffer over `range` (which must be within the size of
155    /// the buffer).
156    pub fn subslice_mut<R: SliceRange>(&mut self, range: R) -> MutableBufferRef<'_> {
157        let new_range = subrange(&self.range, &range);
158        let relative_range =
159            (new_range.start - self.range.start)..(new_range.end - self.range.start);
160        let slice = self.slice.reborrow().subslice_mut(relative_range);
161        MutableBufferRef {
162            slice,
163            range: new_range,
164            allocator_id: self.allocator.borrow().identifier(),
165            trusted: self.allocator.borrow().is_trusted(),
166        }
167    }
168
169    /// Returns the buffer's capacity.
170    pub fn len(&self) -> usize {
171        self.range.end - self.range.start
172    }
173
174    /// Returns the physical addresses for DMA if this buffer is pinned by its allocator.
175    #[cfg(target_os = "fuchsia")]
176    pub fn paddrs(&self) -> Option<&[zx_paddr_t]> {
177        self.allocator.borrow().paddrs(&self.range).map(|(paddrs, _)| paddrs)
178    }
179
180    /// Returns the contiguity used when pinning this buffer, if pinned by its allocator.
181    #[cfg(target_os = "fuchsia")]
182    pub fn contiguity(&self) -> Option<u64> {
183        self.allocator.borrow().paddrs(&self.range).map(|(_, contig)| contig)
184    }
185
186    /// Returns the underlying VMO if the buffer is untrusted and backed by a VMO.
187    ///
188    /// Returns `None` if the buffer is trusted.
189    #[cfg(target_os = "fuchsia")]
190    pub fn vmo(&self) -> Option<Arc<zx::Vmo>> {
191        self.allocator.borrow().vmo()
192    }
193
194    /// Returns a reference to the underlying data if the buffer is trusted.
195    /// Returns None if the buffer is untrusted (shared with the driver).
196    pub fn try_as_slice(&self) -> Option<&[u8]> {
197        if self.allocator.borrow().is_trusted() {
198            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
199            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
200        } else {
201            None
202        }
203    }
204
205    /// Returns a mutable reference to the underlying data if the buffer is trusted.
206    /// Returns None if the buffer is untrusted (shared with the driver).
207    pub fn try_as_mut_slice(&mut self) -> Option<&mut [u8]> {
208        if self.allocator.borrow().is_trusted() {
209            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
210            Some(unsafe { std::slice::from_raw_parts_mut(self.slice.as_mut_ptr(), self.len()) })
211        } else {
212            None
213        }
214    }
215
216    /// Copies the contents of this buffer into `dest`.
217    ///
218    /// # Panics
219    ///
220    /// Panics if `dest.len() != self.len()`.
221    pub fn copy_to_slice(&self, dest: &mut [u8]) {
222        self.slice.as_ptr_slice().copy_to_slice(dest);
223    }
224
225    /// Copies the contents of `src` into this buffer.
226    ///
227    /// # Panics
228    ///
229    /// Panics if `src.len() != self.len()`.
230    pub fn copy_from_slice(&mut self, src: &[u8]) {
231        self.slice.copy_from_ptr_slice(src.into());
232    }
233
234    /// Copies the contents of `src` buffer into this buffer.
235    ///
236    /// # Panics
237    ///
238    /// Panics if `src.len() != self.len()`.
239    pub fn copy_from_buffer(&mut self, src: BufferRef<'_>) {
240        self.as_mut().copy_from_buffer(src);
241    }
242
243    /// Fills the buffer with `val`.
244    pub fn fill(&mut self, val: u8) {
245        self.slice.fill(val);
246    }
247
248    /// Returns the range in the underlying BufferSource that this buffer covers.
249    pub fn range(&self) -> Range<usize> {
250        self.range.clone()
251    }
252
253    /// Returns a reference to the allocator.
254    pub fn allocator(&self) -> &A {
255        self.allocator.borrow()
256    }
257
258    /// Returns the buffer's contents as a Vec.
259    pub fn to_vec(&self) -> Vec<u8> {
260        self.as_ref().to_vec()
261    }
262
263    /// Appends the buffer's contents to `vec`.
264    pub fn append_to(&self, vec: &mut Vec<u8>) {
265        self.as_ref().append_to(vec)
266    }
267
268    /// Returns a raw pointer to the buffer's contents.
269    pub fn as_ptr(&self) -> *const u8 {
270        self.slice.as_ptr()
271    }
272
273    /// Returns a mutable raw pointer to the buffer's contents.
274    pub fn as_mut_ptr(&mut self) -> *mut u8 {
275        self.slice.as_mut_ptr()
276    }
277
278    /// Returns a read-only pointer slice over the buffer.
279    pub fn as_ptr_slice(&self) -> PtrByteSlice<'_> {
280        self.slice.as_ptr_slice()
281    }
282
283    /// Returns a mutable pointer slice over the buffer.
284    pub fn as_mut_ptr_slice(&mut self) -> MutPtrByteSlice<'_> {
285        self.slice.reborrow()
286    }
287}
288
289impl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> Drop for BufferImpl<'a, H, A> {
290    fn drop(&mut self) {
291        self.allocator.borrow().free_buffer(self.range.clone());
292    }
293}
294
295/// BufferRef is an unowned, read-only view over a Buffer.
296#[derive(Clone, Copy, Debug)]
297pub struct BufferRef<'a> {
298    slice: PtrByteSlice<'a>,
299    start: usize, // Not range so that we get Copy.
300    end: usize,
301    /// Opaque identifier derived from the memory address of the `BufferAllocator`.
302    /// Used internally to detect foreign buffers allocated from a different allocator.
303    allocator_id: usize,
304    trusted: bool,
305}
306
307impl<'a> BufferRef<'a> {
308    /// Returns the buffer's capacity.
309    pub fn len(&self) -> usize {
310        self.end - self.start
311    }
312
313    pub fn is_empty(&self) -> bool {
314        self.end == self.start
315    }
316
317    #[cfg(target_os = "fuchsia")]
318    pub(crate) fn allocator_id(&self) -> usize {
319        self.allocator_id
320    }
321
322    /// Returns a reference to the underlying data if the buffer is trusted.
323    /// Returns None if the buffer is untrusted (shared with the driver).
324    pub fn try_as_slice(&self) -> Option<&[u8]> {
325        if self.trusted {
326            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
327            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
328        } else {
329            None
330        }
331    }
332
333    /// Slices and consumes this reference. See Buffer::subslice.
334    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
335        let new_range = subrange(&self.range(), &range);
336        let relative_range = (new_range.start - self.start)..(new_range.end - self.start);
337        let slice = self.slice.subslice(relative_range);
338        BufferRef {
339            slice,
340            start: new_range.start,
341            end: new_range.end,
342            allocator_id: self.allocator_id,
343            trusted: self.trusted,
344        }
345    }
346
347    /// Splits at `mid` (included in the right child), yielding two BufferRefs.
348    pub fn split_at(&self, mid: usize) -> (BufferRef<'a>, BufferRef<'a>) {
349        let ranges = split_range(&self.range(), mid);
350        let (left_slice, right_slice) = self.slice.split_at(mid);
351        (
352            BufferRef {
353                slice: left_slice,
354                start: ranges.0.start,
355                end: ranges.0.end,
356                allocator_id: self.allocator_id,
357                trusted: self.trusted,
358            },
359            BufferRef {
360                slice: right_slice,
361                start: ranges.1.start,
362                end: ranges.1.end,
363                allocator_id: self.allocator_id,
364                trusted: self.trusted,
365            },
366        )
367    }
368
369    /// Returns an iterator over byte chunks of up to `chunk_size` bytes.
370    ///
371    /// # Panics
372    ///
373    /// Panics if `chunk_size` is 0.
374    pub fn chunks(self, chunk_size: usize) -> Chunks<'a> {
375        Chunks {
376            inner: self.slice.chunks(chunk_size),
377            start: self.start,
378            allocator_id: self.allocator_id,
379            trusted: self.trusted,
380        }
381    }
382
383    /// Returns the range in the underlying BufferSource that this BufferRef covers.
384    pub fn range(&self) -> Range<usize> {
385        self.start..self.end
386    }
387
388    /// Copies the contents of this buffer into `dest`.
389    ///
390    /// # Panics
391    ///
392    /// Panics if `dest.len() != self.len()`.
393    pub fn copy_to_slice(&self, dest: &mut [u8]) {
394        self.slice.copy_to_slice(dest);
395    }
396
397    /// Returns the buffer's contents as a Vec.
398    pub fn to_vec(&self) -> Vec<u8> {
399        self.slice.to_vec()
400    }
401
402    /// Appends the buffer's contents to `vec`.
403    pub fn append_to(&self, vec: &mut Vec<u8>) {
404        self.slice.append_to(vec);
405    }
406
407    /// Returns a raw pointer to the buffer's contents.
408    pub fn as_ptr(&self) -> *const u8 {
409        self.slice.as_ptr()
410    }
411
412    /// Returns a read-only pointer slice over the buffer.
413    pub fn as_ptr_slice(&self) -> PtrByteSlice<'a> {
414        self.slice
415    }
416}
417
418/// MutableBufferRef is an unowned, read-write view of a Buffer.
419#[derive(Debug)]
420pub struct MutableBufferRef<'a> {
421    slice: MutPtrByteSlice<'a>,
422    range: Range<usize>,
423    /// Opaque identifier derived from the memory address of the `BufferAllocator`.
424    /// Used internally to detect foreign buffers allocated from a different allocator.
425    allocator_id: usize,
426    trusted: bool,
427}
428
429impl<'a> MutableBufferRef<'a> {
430    /// Returns the buffer's capacity.
431    pub fn len(&self) -> usize {
432        self.range.end - self.range.start
433    }
434
435    pub fn is_empty(&self) -> bool {
436        self.range.end == self.range.start
437    }
438
439    #[cfg(target_os = "fuchsia")]
440    pub(crate) fn allocator_id(&self) -> usize {
441        self.allocator_id
442    }
443
444    /// Returns a read-only view of the buffer.
445    pub fn as_ref(&self) -> BufferRef<'_> {
446        BufferRef {
447            slice: self.slice.as_ptr_slice(),
448            start: self.range.start,
449            end: self.range.end,
450            allocator_id: self.allocator_id,
451            trusted: self.trusted,
452        }
453    }
454
455    /// Consumes this reference and returns a read-only view.
456    pub fn into_ref(self) -> BufferRef<'a> {
457        BufferRef {
458            slice: self.slice.into(),
459            start: self.range.start,
460            end: self.range.end,
461            allocator_id: self.allocator_id,
462            trusted: self.trusted,
463        }
464    }
465
466    /// Returns a reference to the underlying data if the buffer is trusted.
467    /// Returns None if the buffer is untrusted (shared with the driver).
468    pub fn try_as_slice(&self) -> Option<&[u8]> {
469        if self.trusted {
470            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
471            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
472        } else {
473            None
474        }
475    }
476
477    /// Returns a mutable reference to the underlying data if the buffer is trusted.
478    /// Returns None if the buffer is untrusted (shared with the driver).
479    pub fn try_as_mut_slice(&mut self) -> Option<&mut [u8]> {
480        if self.trusted {
481            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
482            Some(unsafe { std::slice::from_raw_parts_mut(self.slice.as_mut_ptr(), self.len()) })
483        } else {
484            None
485        }
486    }
487
488    /// Reborrows this reference with a lesser lifetime. This mirrors the usual borrowing semantics
489    /// (i.e. the borrow ends when the new reference goes out of scope), and exists so that a
490    /// MutableBufferRef can be subsliced without consuming it.
491    ///
492    /// For example:
493    ///    let mut buf: MutableBufferRef<'_> = ...;
494    ///    {
495    ///        let sub = buf.reborrow().subslice_mut(a..b);
496    ///    }
497    pub fn reborrow(&mut self) -> MutableBufferRef<'_> {
498        MutableBufferRef {
499            slice: self.slice.reborrow(),
500            range: self.range.clone(),
501            allocator_id: self.allocator_id,
502            trusted: self.trusted,
503        }
504    }
505
506    /// Returns an `io::Write` adapter for this buffer.
507    pub fn writer(&mut self) -> storage_ptr_slice::Writer<'_> {
508        self.slice.reborrow().writer()
509    }
510
511    /// Slices this reference. See Buffer::subslice.
512    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
513        let new_range = subrange(&self.range, &range);
514        let relative_range =
515            (new_range.start - self.range.start)..(new_range.end - self.range.start);
516        let slice = self.slice.as_ptr_slice().subslice(relative_range);
517        BufferRef {
518            slice,
519            start: new_range.start,
520            end: new_range.end,
521            allocator_id: self.allocator_id,
522            trusted: self.trusted,
523        }
524    }
525
526    /// Slices and consumes this reference. See Buffer::subslice_mut.
527    pub fn subslice_mut<R: SliceRange>(mut self, range: R) -> MutableBufferRef<'a> {
528        let new_range = subrange(&self.range, &range);
529        let relative_range =
530            (new_range.start - self.range.start)..(new_range.end - self.range.start);
531        self.slice = self.slice.subslice_mut(relative_range);
532        self.range = new_range;
533        self
534    }
535
536    /// Splits at `mid` (included in the right child), yielding two BufferRefs.
537    pub fn split_at(&self, mid: usize) -> (BufferRef<'_>, BufferRef<'_>) {
538        let ranges = split_range(&self.range, mid);
539        let (left_slice, right_slice) = self.slice.as_ptr_slice().split_at(mid);
540        (
541            BufferRef {
542                slice: left_slice,
543                start: ranges.0.start,
544                end: ranges.0.end,
545                allocator_id: self.allocator_id,
546                trusted: self.trusted,
547            },
548            BufferRef {
549                slice: right_slice,
550                start: ranges.1.start,
551                end: ranges.1.end,
552                allocator_id: self.allocator_id,
553                trusted: self.trusted,
554            },
555        )
556    }
557
558    /// Consumes the reference and splits it at `mid` (included in the right child), yielding two
559    /// MutableBufferRefs.
560    pub fn split_at_mut(self, mid: usize) -> (MutableBufferRef<'a>, MutableBufferRef<'a>) {
561        let ranges = split_range(&self.range, mid);
562        let (left_slice, right_slice) = self.slice.split_at_mut(mid);
563        (
564            MutableBufferRef {
565                slice: left_slice,
566                range: ranges.0,
567                allocator_id: self.allocator_id,
568                trusted: self.trusted,
569            },
570            MutableBufferRef {
571                slice: right_slice,
572                range: ranges.1,
573                allocator_id: self.allocator_id,
574                trusted: self.trusted,
575            },
576        )
577    }
578
579    /// Returns the range in the underlying BufferSource that this MutableBufferRef covers.
580    pub fn range(&self) -> Range<usize> {
581        self.range.clone()
582    }
583
584    /// Copies the contents of this buffer into `dest`.
585    ///
586    /// # Panics
587    ///
588    /// Panics if `dest.len() != self.len()`.
589    pub fn copy_to_slice(&self, dest: &mut [u8]) {
590        self.slice.copy_to_slice(dest);
591    }
592
593    /// Copies the contents of `src` into this buffer.
594    ///
595    /// # Panics
596    ///
597    /// Panics if `src.len() != self.len()`.
598    pub fn copy_from_slice(&mut self, src: &[u8]) {
599        self.slice.copy_from_ptr_slice(src.into());
600    }
601
602    /// Copies the contents of `src` buffer into this buffer.
603    ///
604    /// # Panics
605    ///
606    /// Panics if `src.len() != self.len()`.
607    pub fn copy_from_buffer(&mut self, src: BufferRef<'_>) {
608        self.slice.copy_from_ptr_slice(src.as_ptr_slice());
609    }
610
611    /// Fills the buffer with `val`.
612    pub fn fill(&mut self, val: u8) {
613        self.slice.fill(val);
614    }
615
616    /// Returns the buffer's contents as a Vec.
617    pub fn to_vec(&self) -> Vec<u8> {
618        self.slice.to_vec()
619    }
620
621    /// Appends the buffer's contents to `vec`.
622    pub fn append_to(&self, vec: &mut Vec<u8>) {
623        self.slice.append_to(vec);
624    }
625
626    /// Returns a raw pointer to the buffer's contents.
627    pub fn as_ptr(&self) -> *const u8 {
628        self.slice.as_ptr()
629    }
630
631    /// Returns a mutable raw pointer to the buffer's contents.
632    pub fn as_mut_ptr(&mut self) -> *mut u8 {
633        self.slice.as_mut_ptr()
634    }
635
636    /// Returns a read-only pointer slice over the buffer.
637    pub fn as_ptr_slice(&self) -> PtrByteSlice<'_> {
638        self.slice.as_ptr_slice()
639    }
640
641    /// Returns a mutable pointer slice over the buffer.
642    pub fn as_mut_ptr_slice(&mut self) -> MutPtrByteSlice<'_> {
643        self.slice.reborrow()
644    }
645
646    /// Returns an iterator over mutable byte chunks of up to `chunk_size` bytes.
647    ///
648    /// # Panics
649    ///
650    /// Panics if `chunk_size` is 0.
651    pub fn chunks_mut(self, chunk_size: usize) -> ChunksMut<'a> {
652        ChunksMut {
653            inner: self.slice.into_chunks_mut(chunk_size),
654            start: self.range.start,
655            allocator_id: self.allocator_id,
656            trusted: self.trusted,
657        }
658    }
659
660    /// Consumes this reference and returns a mutable pointer slice.
661    pub fn into_mut_ptr_slice(self) -> MutPtrByteSlice<'a> {
662        self.slice
663    }
664}
665
666/// An iterator over slice chunks of a `BufferRef`.
667#[derive(Debug)]
668pub struct Chunks<'a> {
669    inner: storage_ptr_slice::Chunks<'a>,
670    start: usize,
671    allocator_id: usize,
672    trusted: bool,
673}
674
675impl<'a> Iterator for Chunks<'a> {
676    type Item = BufferRef<'a>;
677
678    fn next(&mut self) -> Option<Self::Item> {
679        let slice = self.inner.next()?;
680        let len = slice.len();
681        let start = self.start;
682        self.start += len;
683        Some(BufferRef {
684            slice,
685            start,
686            end: start + len,
687            allocator_id: self.allocator_id,
688            trusted: self.trusted,
689        })
690    }
691
692    fn size_hint(&self) -> (usize, Option<usize>) {
693        self.inner.size_hint()
694    }
695}
696
697impl ExactSizeIterator for Chunks<'_> {
698    fn len(&self) -> usize {
699        self.inner.len()
700    }
701}
702
703impl std::iter::FusedIterator for Chunks<'_> {}
704
705/// An iterator over mutable slice chunks of a `MutableBufferRef`.
706#[derive(Debug)]
707pub struct ChunksMut<'a> {
708    inner: storage_ptr_slice::ChunksMut<'a>,
709    start: usize,
710    allocator_id: usize,
711    trusted: bool,
712}
713
714impl<'a> Iterator for ChunksMut<'a> {
715    type Item = MutableBufferRef<'a>;
716
717    fn next(&mut self) -> Option<Self::Item> {
718        let slice = self.inner.next()?;
719        let len = slice.len();
720        let start = self.start;
721        self.start += len;
722        Some(MutableBufferRef {
723            slice,
724            range: start..start + len,
725            allocator_id: self.allocator_id,
726            trusted: self.trusted,
727        })
728    }
729
730    fn size_hint(&self) -> (usize, Option<usize>) {
731        self.inner.size_hint()
732    }
733}
734
735impl ExactSizeIterator for ChunksMut<'_> {
736    fn len(&self) -> usize {
737        self.inner.len()
738    }
739}
740
741impl std::iter::FusedIterator for ChunksMut<'_> {}
742
743#[cfg(test)]
744mod tests {
745    use crate::buffer_allocator::{BufferAllocator, BufferSource};
746
747    #[test]
748    fn test_buffer_refs_are_send_and_sync() {
749        fn check<'a>() {
750            fn assert_send_sync<T: Send + Sync>() {}
751            assert_send_sync::<super::BufferRef<'a>>();
752            assert_send_sync::<super::MutableBufferRef<'a>>();
753        }
754        check();
755    }
756
757    #[fuchsia::test]
758    async fn test_chunks() {
759        let source = BufferSource::new(1024 * 1024);
760        let allocator = BufferAllocator::new(512, source);
761        let mut buf = allocator.allocate_buffer(1000).await;
762        let init_data: Vec<u8> = (0..1000).map(|i| (i % 256) as u8).collect();
763        buf.as_mut().copy_from_slice(&init_data);
764
765        let bref = buf.as_ref();
766        let chunks: Vec<_> = bref.chunks(300).collect();
767        assert_eq!(chunks.len(), 4);
768        assert_eq!(chunks[0].len(), 300);
769        assert_eq!(chunks[1].len(), 300);
770        assert_eq!(chunks[2].len(), 300);
771        assert_eq!(chunks[3].len(), 100);
772
773        let mut data = vec![0u8; 300];
774        chunks[0].copy_to_slice(&mut data);
775        assert_eq!(data, (0..300).map(|i| (i % 256) as u8).collect::<Vec<u8>>());
776
777        let mut data_last = vec![0u8; 100];
778        chunks[3].copy_to_slice(&mut data_last);
779        assert_eq!(data_last, (900..1000).map(|i| (i % 256) as u8).collect::<Vec<u8>>());
780
781        // Test exact multiple
782        let bref_exact = buf.subslice(0..600);
783        let chunks_exact: Vec<_> = bref_exact.chunks(200).collect();
784        assert_eq!(chunks_exact.len(), 3);
785        assert_eq!(chunks_exact.iter().map(|c| c.len()).collect::<Vec<_>>(), vec![200, 200, 200]);
786
787        // Test empty buffer
788        let bref_empty = buf.subslice(0..0);
789        assert_eq!(bref_empty.chunks(100).count(), 0);
790        assert_eq!(bref_empty.chunks(100).len(), 0);
791
792        // Test chunk larger than buffer
793        let chunks_large: Vec<_> = bref.chunks(2000).collect();
794        assert_eq!(chunks_large.len(), 1);
795        assert_eq!(chunks_large[0].len(), 1000);
796
797        // Test ExactSizeIterator and size_hint
798        let mut iter = bref.chunks(300);
799        assert_eq!(iter.len(), 4);
800        assert_eq!(iter.size_hint(), (4, Some(4)));
801        assert_eq!(iter.next().unwrap().len(), 300);
802        assert_eq!(iter.len(), 3);
803        assert_eq!(iter.size_hint(), (3, Some(3)));
804        assert_eq!(iter.next().unwrap().len(), 300);
805        assert_eq!(iter.len(), 2);
806        assert_eq!(iter.size_hint(), (2, Some(2)));
807        assert_eq!(iter.next().unwrap().len(), 300);
808        assert_eq!(iter.len(), 1);
809        assert_eq!(iter.size_hint(), (1, Some(1)));
810        assert_eq!(iter.next().unwrap().len(), 100);
811        assert_eq!(iter.len(), 0);
812        assert_eq!(iter.size_hint(), (0, Some(0)));
813        assert!(iter.next().is_none());
814    }
815
816    #[fuchsia::test]
817    async fn test_chunks_mut() {
818        let source = BufferSource::new(1024 * 1024);
819        let allocator = BufferAllocator::new(512, source);
820        let mut buf = allocator.allocate_buffer(1000).await;
821
822        for (i, mut chunk) in buf.as_mut().chunks_mut(300).enumerate() {
823            chunk.fill(i as u8 + 1);
824        }
825
826        let mut data = vec![0u8; 1000];
827        buf.copy_to_slice(&mut data);
828        assert_eq!(&data[0..300], &[1u8; 300]);
829        assert_eq!(&data[300..600], &[2u8; 300]);
830        assert_eq!(&data[600..900], &[3u8; 300]);
831        assert_eq!(&data[900..1000], &[4u8; 100]);
832
833        // Test exact multiple
834        let mut buf_exact = allocator.allocate_buffer(600).await;
835        for (i, mut chunk) in buf_exact.as_mut().chunks_mut(200).enumerate() {
836            chunk.fill((i + 10) as u8);
837        }
838        let mut data_exact = vec![0u8; 600];
839        buf_exact.copy_to_slice(&mut data_exact);
840        assert_eq!(&data_exact[0..200], &[10u8; 200]);
841        assert_eq!(&data_exact[200..400], &[11u8; 200]);
842        assert_eq!(&data_exact[400..600], &[12u8; 200]);
843
844        // Test empty buffer
845        let mut buf_empty = allocator.allocate_buffer(512).await;
846        let empty_ref = buf_empty.subslice_mut(0..0);
847        assert_eq!(empty_ref.chunks_mut(100).count(), 0);
848
849        // Test ExactSizeIterator on chunks_mut
850        let mut buf_exact_iter = allocator.allocate_buffer(1000).await;
851        let mut iter = buf_exact_iter.as_mut().chunks_mut(300);
852        assert_eq!(iter.len(), 4);
853        assert_eq!(iter.size_hint(), (4, Some(4)));
854        let mut c1 = iter.next().unwrap();
855        c1.fill(0x11);
856        assert_eq!(iter.len(), 3);
857        assert_eq!(iter.size_hint(), (3, Some(3)));
858        let mut c2 = iter.next().unwrap();
859        c2.fill(0x22);
860        assert_eq!(iter.len(), 2);
861        assert_eq!(iter.size_hint(), (2, Some(2)));
862        let mut c3 = iter.next().unwrap();
863        c3.fill(0x33);
864        assert_eq!(iter.len(), 1);
865        assert_eq!(iter.size_hint(), (1, Some(1)));
866        let mut c4 = iter.next().unwrap();
867        c4.fill(0x44);
868        assert_eq!(iter.len(), 0);
869        assert_eq!(iter.size_hint(), (0, Some(0)));
870        assert!(iter.next().is_none());
871
872        let mut data_iter = vec![0u8; 1000];
873        buf_exact_iter.copy_to_slice(&mut data_iter);
874        assert_eq!(&data_iter[0..300], &[0x11; 300]);
875        assert_eq!(&data_iter[300..600], &[0x22; 300]);
876        assert_eq!(&data_iter[600..900], &[0x33; 300]);
877        assert_eq!(&data_iter[900..1000], &[0x44; 100]);
878    }
879}