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;
13
14/// An entity capable of reclaiming a memory buffer range when dropped.
15pub trait BufferAllocator: Send + Sync + std::fmt::Debug + 'static {
16    /// Frees or reclaims the specified memory range.
17    fn free_buffer(&self, range: Range<usize>);
18
19    /// Returns an identifier for this allocator based on its memory address.
20    fn identifier(&self) -> usize {
21        std::ptr::from_ref(self).addr()
22    }
23
24    /// Returns true if buffers produced by this allocator are trusted (unshared).
25    fn is_trusted(&self) -> bool {
26        false
27    }
28}
29
30pub(super) fn round_down<T>(value: T, granularity: T) -> T
31where
32    T: num::Num + Copy,
33{
34    value - value % granularity
35}
36
37pub(super) fn round_up<T>(value: T, granularity: T) -> T
38where
39    T: num::Num + Copy,
40{
41    round_down(value + granularity - T::one(), granularity)
42}
43
44// Returns a range within a range.
45// For example, subrange(100..200, 20..30) = 120..130.
46fn subrange<R: RangeBounds<usize>>(source: &Range<usize>, bounds: &R) -> Range<usize> {
47    let subrange = (match bounds.start_bound() {
48        Bound::Included(&s) => source.start + s,
49        Bound::Excluded(&s) => source.start + s + 1,
50        Bound::Unbounded => source.start,
51    })..(match bounds.end_bound() {
52        Bound::Included(&e) => source.start + e + 1,
53        Bound::Excluded(&e) => source.start + e,
54        Bound::Unbounded => source.end,
55    });
56    assert!(subrange.end <= source.end);
57    subrange
58}
59
60fn split_range(range: &Range<usize>, mid: usize) -> (Range<usize>, Range<usize>) {
61    let l = range.end - range.start;
62    let base = range.start;
63    (base..base + mid, base + mid..base + l)
64}
65
66/// Buffer is a read-write buffer that can be used for I/O with the block device. They are created
67/// by a BufferAllocator, and automatically deallocate themselves when they go out of scope.
68///
69/// Most usage will be on the unowned BufferRef and MutableBufferRef types, since these types are
70/// used for Device::read and Device::write.
71///
72/// Buffers are always block-aligned (both in offset and length), but unaligned slices can be made
73/// with the reference types. That said, the Device trait requires aligned BufferRef and
74/// MutableBufferRef objects, so alignment must be restored by the time a device read/write is
75/// requested.
76///
77/// For example, when writing an unaligned amount of data to the device, generally two Buffers
78/// would need to be involved; the input Buffer could be used to write everything up to the last
79/// block, and a second single-block alignment Buffer would be used to read-modify-update the last
80/// block.
81use std::sync::Arc;
82
83#[derive(Debug)]
84pub struct BufferImpl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> {
85    slice: MutPtrByteSlice<'a>,
86    range: Range<usize>,
87    allocator: H,
88    _phantom: PhantomData<fn() -> &'a A>,
89}
90
91pub type Buffer<'a> = BufferImpl<'a, &'a PoolBufferAllocator, PoolBufferAllocator>;
92pub type OwnedBuffer = BufferImpl<'static, Arc<dyn BufferAllocator>, dyn BufferAllocator>;
93
94// Alias for the traits which need to be satisfied for `subslice` and friends.
95// This trait is automatically satisfied for most typical uses (a..b, a.., ..b, ..).
96pub trait SliceRange: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
97impl<T> SliceRange for T where T: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
98
99impl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> BufferImpl<'a, H, A> {
100    pub(super) fn new(slice: MutPtrByteSlice<'a>, range: Range<usize>, allocator: H) -> Self {
101        assert_eq!(slice.len(), range.end - range.start);
102        Self { slice, range, allocator, _phantom: PhantomData }
103    }
104
105    /// Takes a read-only reference to this buffer.
106    pub fn as_ref(&self) -> BufferRef<'_> {
107        self.subslice(..)
108    }
109
110    /// Takes a read-only reference to this buffer over `range` (which must be within the size of
111    /// the buffer).
112    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
113        let new_range = subrange(&self.range, &range);
114        let relative_range =
115            (new_range.start - self.range.start)..(new_range.end - self.range.start);
116        let slice = self.slice.as_ptr_slice().subslice(relative_range);
117        BufferRef {
118            slice,
119            start: new_range.start,
120            end: new_range.end,
121            allocator_id: self.allocator.borrow().identifier(),
122            trusted: self.allocator.borrow().is_trusted(),
123        }
124    }
125
126    /// Takes a read-write reference to this buffer.
127    pub fn as_mut(&mut self) -> MutableBufferRef<'_> {
128        self.subslice_mut(..)
129    }
130
131    /// Returns an `io::Write` adapter for this buffer.
132    pub fn writer(&mut self) -> storage_ptr_slice::Writer<'_> {
133        self.slice.reborrow().writer()
134    }
135
136    /// Takes a read-write reference to this buffer over `range` (which must be within the size of
137    /// the buffer).
138    pub fn subslice_mut<R: SliceRange>(&mut self, range: R) -> MutableBufferRef<'_> {
139        let new_range = subrange(&self.range, &range);
140        let relative_range =
141            (new_range.start - self.range.start)..(new_range.end - self.range.start);
142        let slice = self.slice.reborrow().subslice_mut(relative_range);
143        MutableBufferRef {
144            slice,
145            range: new_range,
146            allocator_id: self.allocator.borrow().identifier(),
147            trusted: self.allocator.borrow().is_trusted(),
148        }
149    }
150
151    /// Returns the buffer's capacity.
152    pub fn len(&self) -> usize {
153        self.range.end - self.range.start
154    }
155
156    /// Returns a reference to the underlying data if the buffer is trusted.
157    /// Returns None if the buffer is untrusted (shared with the driver).
158    pub fn try_as_slice(&self) -> Option<&[u8]> {
159        if self.allocator.borrow().is_trusted() {
160            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
161            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
162        } else {
163            None
164        }
165    }
166
167    /// Returns a mutable reference to the underlying data if the buffer is trusted.
168    /// Returns None if the buffer is untrusted (shared with the driver).
169    pub fn try_as_mut_slice(&mut self) -> Option<&mut [u8]> {
170        if self.allocator.borrow().is_trusted() {
171            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
172            Some(unsafe { std::slice::from_raw_parts_mut(self.slice.as_mut_ptr(), self.len()) })
173        } else {
174            None
175        }
176    }
177
178    /// Copies the contents of this buffer into `dest`.
179    ///
180    /// # Panics
181    ///
182    /// Panics if `dest.len() != self.len()`.
183    pub fn copy_to_slice(&self, dest: &mut [u8]) {
184        self.slice.as_ptr_slice().copy_to_slice(dest);
185    }
186
187    /// Copies the contents of `src` into this buffer.
188    ///
189    /// # Panics
190    ///
191    /// Panics if `src.len() != self.len()`.
192    pub fn copy_from_slice(&mut self, src: &[u8]) {
193        self.slice.copy_from_ptr_slice(src.into());
194    }
195
196    /// Copies the contents of `src` buffer into this buffer.
197    ///
198    /// # Panics
199    ///
200    /// Panics if `src.len() != self.len()`.
201    pub fn copy_from_buffer(&mut self, src: BufferRef<'_>) {
202        self.as_mut().copy_from_buffer(src);
203    }
204
205    /// Fills the buffer with `val`.
206    pub fn fill(&mut self, val: u8) {
207        self.slice.fill(val);
208    }
209
210    /// Returns the range in the underlying BufferSource that this buffer covers.
211    pub fn range(&self) -> Range<usize> {
212        self.range.clone()
213    }
214
215    /// Returns a reference to the allocator.
216    pub fn allocator(&self) -> &A {
217        self.allocator.borrow()
218    }
219
220    /// Returns the buffer's contents as a Vec.
221    pub fn to_vec(&self) -> Vec<u8> {
222        self.as_ref().to_vec()
223    }
224
225    /// Appends the buffer's contents to `vec`.
226    pub fn append_to(&self, vec: &mut Vec<u8>) {
227        self.as_ref().append_to(vec)
228    }
229
230    /// Returns a raw pointer to the buffer's contents.
231    pub fn as_ptr(&self) -> *const u8 {
232        self.slice.as_ptr()
233    }
234
235    /// Returns a mutable raw pointer to the buffer's contents.
236    pub fn as_mut_ptr(&mut self) -> *mut u8 {
237        self.slice.as_mut_ptr()
238    }
239
240    /// Returns a read-only pointer slice over the buffer.
241    pub fn as_ptr_slice(&self) -> PtrByteSlice<'_> {
242        self.slice.as_ptr_slice()
243    }
244
245    /// Returns a mutable pointer slice over the buffer.
246    pub fn as_mut_ptr_slice(&mut self) -> MutPtrByteSlice<'_> {
247        self.slice.reborrow()
248    }
249}
250
251impl<'a, H: Borrow<A>, A: ?Sized + BufferAllocator> Drop for BufferImpl<'a, H, A> {
252    fn drop(&mut self) {
253        self.allocator.borrow().free_buffer(self.range.clone());
254    }
255}
256
257/// BufferRef is an unowned, read-only view over a Buffer.
258#[derive(Clone, Copy, Debug)]
259pub struct BufferRef<'a> {
260    slice: PtrByteSlice<'a>,
261    start: usize, // Not range so that we get Copy.
262    end: usize,
263    /// Opaque identifier derived from the memory address of the `BufferAllocator`.
264    /// Used internally to detect foreign buffers allocated from a different allocator.
265    allocator_id: usize,
266    trusted: bool,
267}
268
269impl<'a> BufferRef<'a> {
270    /// Returns the buffer's capacity.
271    pub fn len(&self) -> usize {
272        self.end - self.start
273    }
274
275    pub fn is_empty(&self) -> bool {
276        self.end == self.start
277    }
278
279    #[cfg(target_os = "fuchsia")]
280    pub(crate) fn allocator_id(&self) -> usize {
281        self.allocator_id
282    }
283
284    /// Returns a reference to the underlying data if the buffer is trusted.
285    /// Returns None if the buffer is untrusted (shared with the driver).
286    pub fn try_as_slice(&self) -> Option<&[u8]> {
287        if self.trusted {
288            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
289            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
290        } else {
291            None
292        }
293    }
294
295    /// Slices and consumes this reference. See Buffer::subslice.
296    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
297        let new_range = subrange(&self.range(), &range);
298        let relative_range = (new_range.start - self.start)..(new_range.end - self.start);
299        let slice = self.slice.subslice(relative_range);
300        BufferRef {
301            slice,
302            start: new_range.start,
303            end: new_range.end,
304            allocator_id: self.allocator_id,
305            trusted: self.trusted,
306        }
307    }
308
309    /// Splits at `mid` (included in the right child), yielding two BufferRefs.
310    pub fn split_at(&self, mid: usize) -> (BufferRef<'_>, BufferRef<'_>) {
311        let ranges = split_range(&self.range(), mid);
312        let (left_slice, right_slice) = self.slice.split_at(mid);
313        (
314            BufferRef {
315                slice: left_slice,
316                start: ranges.0.start,
317                end: ranges.0.end,
318                allocator_id: self.allocator_id,
319                trusted: self.trusted,
320            },
321            BufferRef {
322                slice: right_slice,
323                start: ranges.1.start,
324                end: ranges.1.end,
325                allocator_id: self.allocator_id,
326                trusted: self.trusted,
327            },
328        )
329    }
330
331    /// Returns the range in the underlying BufferSource that this BufferRef covers.
332    pub fn range(&self) -> Range<usize> {
333        self.start..self.end
334    }
335
336    /// Copies the contents of this buffer into `dest`.
337    ///
338    /// # Panics
339    ///
340    /// Panics if `dest.len() != self.len()`.
341    pub fn copy_to_slice(&self, dest: &mut [u8]) {
342        self.slice.copy_to_slice(dest);
343    }
344
345    /// Returns the buffer's contents as a Vec.
346    pub fn to_vec(&self) -> Vec<u8> {
347        self.slice.to_vec()
348    }
349
350    /// Appends the buffer's contents to `vec`.
351    pub fn append_to(&self, vec: &mut Vec<u8>) {
352        self.slice.append_to(vec);
353    }
354
355    /// Returns a raw pointer to the buffer's contents.
356    pub fn as_ptr(&self) -> *const u8 {
357        self.slice.as_ptr()
358    }
359
360    /// Returns a read-only pointer slice over the buffer.
361    pub fn as_ptr_slice(&self) -> PtrByteSlice<'a> {
362        self.slice
363    }
364}
365
366/// MutableBufferRef is an unowned, read-write view of a Buffer.
367#[derive(Debug)]
368pub struct MutableBufferRef<'a> {
369    slice: MutPtrByteSlice<'a>,
370    range: Range<usize>,
371    /// Opaque identifier derived from the memory address of the `BufferAllocator`.
372    /// Used internally to detect foreign buffers allocated from a different allocator.
373    allocator_id: usize,
374    trusted: bool,
375}
376
377impl<'a> MutableBufferRef<'a> {
378    /// Returns the buffer's capacity.
379    pub fn len(&self) -> usize {
380        self.range.end - self.range.start
381    }
382
383    pub fn is_empty(&self) -> bool {
384        self.range.end == self.range.start
385    }
386
387    #[cfg(target_os = "fuchsia")]
388    pub(crate) fn allocator_id(&self) -> usize {
389        self.allocator_id
390    }
391
392    /// Returns a read-only view of the buffer.
393    pub fn as_ref(&self) -> BufferRef<'_> {
394        BufferRef {
395            slice: self.slice.as_ptr_slice(),
396            start: self.range.start,
397            end: self.range.end,
398            allocator_id: self.allocator_id,
399            trusted: self.trusted,
400        }
401    }
402
403    /// Consumes this reference and returns a read-only view.
404    pub fn into_ref(self) -> BufferRef<'a> {
405        BufferRef {
406            slice: self.slice.into(),
407            start: self.range.start,
408            end: self.range.end,
409            allocator_id: self.allocator_id,
410            trusted: self.trusted,
411        }
412    }
413
414    /// Returns a reference to the underlying data if the buffer is trusted.
415    /// Returns None if the buffer is untrusted (shared with the driver).
416    pub fn try_as_slice(&self) -> Option<&[u8]> {
417        if self.trusted {
418            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
419            Some(unsafe { std::slice::from_raw_parts(self.slice.as_ptr(), self.len()) })
420        } else {
421            None
422        }
423    }
424
425    /// Returns a mutable reference to the underlying data if the buffer is trusted.
426    /// Returns None if the buffer is untrusted (shared with the driver).
427    pub fn try_as_mut_slice(&mut self) -> Option<&mut [u8]> {
428        if self.trusted {
429            // SAFETY: The buffer is trusted (not shared), so no concurrent mutation can occur.
430            Some(unsafe { std::slice::from_raw_parts_mut(self.slice.as_mut_ptr(), self.len()) })
431        } else {
432            None
433        }
434    }
435
436    /// Reborrows this reference with a lesser lifetime. This mirrors the usual borrowing semantics
437    /// (i.e. the borrow ends when the new reference goes out of scope), and exists so that a
438    /// MutableBufferRef can be subsliced without consuming it.
439    ///
440    /// For example:
441    ///    let mut buf: MutableBufferRef<'_> = ...;
442    ///    {
443    ///        let sub = buf.reborrow().subslice_mut(a..b);
444    ///    }
445    pub fn reborrow(&mut self) -> MutableBufferRef<'_> {
446        MutableBufferRef {
447            slice: self.slice.reborrow(),
448            range: self.range.clone(),
449            allocator_id: self.allocator_id,
450            trusted: self.trusted,
451        }
452    }
453
454    /// Returns an `io::Write` adapter for this buffer.
455    pub fn writer(&mut self) -> storage_ptr_slice::Writer<'_> {
456        self.slice.reborrow().writer()
457    }
458
459    /// Slices this reference. See Buffer::subslice.
460    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
461        let new_range = subrange(&self.range, &range);
462        let relative_range =
463            (new_range.start - self.range.start)..(new_range.end - self.range.start);
464        let slice = self.slice.as_ptr_slice().subslice(relative_range);
465        BufferRef {
466            slice,
467            start: new_range.start,
468            end: new_range.end,
469            allocator_id: self.allocator_id,
470            trusted: self.trusted,
471        }
472    }
473
474    /// Slices and consumes this reference. See Buffer::subslice_mut.
475    pub fn subslice_mut<R: SliceRange>(mut self, range: R) -> MutableBufferRef<'a> {
476        let new_range = subrange(&self.range, &range);
477        let relative_range =
478            (new_range.start - self.range.start)..(new_range.end - self.range.start);
479        self.slice = self.slice.subslice_mut(relative_range);
480        self.range = new_range;
481        self
482    }
483
484    /// Splits at `mid` (included in the right child), yielding two BufferRefs.
485    pub fn split_at(&self, mid: usize) -> (BufferRef<'_>, BufferRef<'_>) {
486        let ranges = split_range(&self.range, mid);
487        let (left_slice, right_slice) = self.slice.as_ptr_slice().split_at(mid);
488        (
489            BufferRef {
490                slice: left_slice,
491                start: ranges.0.start,
492                end: ranges.0.end,
493                allocator_id: self.allocator_id,
494                trusted: self.trusted,
495            },
496            BufferRef {
497                slice: right_slice,
498                start: ranges.1.start,
499                end: ranges.1.end,
500                allocator_id: self.allocator_id,
501                trusted: self.trusted,
502            },
503        )
504    }
505
506    /// Consumes the reference and splits it at `mid` (included in the right child), yielding two
507    /// MutableBufferRefs.
508    pub fn split_at_mut(self, mid: usize) -> (MutableBufferRef<'a>, MutableBufferRef<'a>) {
509        let ranges = split_range(&self.range, mid);
510        let (left_slice, right_slice) = self.slice.split_at_mut(mid);
511        (
512            MutableBufferRef {
513                slice: left_slice,
514                range: ranges.0,
515                allocator_id: self.allocator_id,
516                trusted: self.trusted,
517            },
518            MutableBufferRef {
519                slice: right_slice,
520                range: ranges.1,
521                allocator_id: self.allocator_id,
522                trusted: self.trusted,
523            },
524        )
525    }
526
527    /// Returns the range in the underlying BufferSource that this MutableBufferRef covers.
528    pub fn range(&self) -> Range<usize> {
529        self.range.clone()
530    }
531
532    /// Copies the contents of this buffer into `dest`.
533    ///
534    /// # Panics
535    ///
536    /// Panics if `dest.len() != self.len()`.
537    pub fn copy_to_slice(&self, dest: &mut [u8]) {
538        self.slice.copy_to_slice(dest);
539    }
540
541    /// Copies the contents of `src` into this buffer.
542    ///
543    /// # Panics
544    ///
545    /// Panics if `src.len() != self.len()`.
546    pub fn copy_from_slice(&mut self, src: &[u8]) {
547        self.slice.copy_from_ptr_slice(src.into());
548    }
549
550    /// Copies the contents of `src` buffer into this buffer.
551    ///
552    /// # Panics
553    ///
554    /// Panics if `src.len() != self.len()`.
555    pub fn copy_from_buffer(&mut self, src: BufferRef<'_>) {
556        self.slice.copy_from_ptr_slice(src.as_ptr_slice());
557    }
558
559    /// Fills the buffer with `val`.
560    pub fn fill(&mut self, val: u8) {
561        self.slice.fill(val);
562    }
563
564    /// Returns the buffer's contents as a Vec.
565    pub fn to_vec(&self) -> Vec<u8> {
566        self.slice.to_vec()
567    }
568
569    /// Appends the buffer's contents to `vec`.
570    pub fn append_to(&self, vec: &mut Vec<u8>) {
571        self.slice.append_to(vec);
572    }
573
574    /// Returns a raw pointer to the buffer's contents.
575    pub fn as_ptr(&self) -> *const u8 {
576        self.slice.as_ptr()
577    }
578
579    /// Returns a mutable raw pointer to the buffer's contents.
580    pub fn as_mut_ptr(&mut self) -> *mut u8 {
581        self.slice.as_mut_ptr()
582    }
583
584    /// Returns a read-only pointer slice over the buffer.
585    pub fn as_ptr_slice(&self) -> PtrByteSlice<'_> {
586        self.slice.as_ptr_slice()
587    }
588
589    /// Returns a mutable pointer slice over the buffer.
590    pub fn as_mut_ptr_slice(&mut self) -> MutPtrByteSlice<'_> {
591        self.slice.reborrow()
592    }
593
594    /// Consumes this reference and returns a mutable pointer slice.
595    pub fn into_mut_ptr_slice(self) -> MutPtrByteSlice<'a> {
596        self.slice
597    }
598}
599
600// SAFETY: BufferRef is a read-only view over allocator-managed memory. It does not allow
601// mutation and behaves like `&[u8]`, which is Send and Sync.
602unsafe impl Send for BufferRef<'_> {}
603// SAFETY: See Send impl above.
604unsafe impl Sync for BufferRef<'_> {}
605
606// SAFETY: MutableBufferRef behaves like `&mut [u8]`. It enforces exclusivity (no overlapping
607// views) and does not have interior mutability, making it safe to Send and Sync.
608unsafe impl Send for MutableBufferRef<'_> {}
609// SAFETY: See Send impl above.
610unsafe impl Sync for MutableBufferRef<'_> {}