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;
6use std::ops::{Bound, Range, RangeBounds};
7use std::slice::SliceIndex;
8
9pub use crate::buffer_allocator::BufferFuture;
10
11pub(super) fn round_down<T>(value: T, granularity: T) -> T
12where
13    T: num::Num + Copy,
14{
15    value - value % granularity
16}
17
18pub(super) fn round_up<T>(value: T, granularity: T) -> T
19where
20    T: num::Num + Copy,
21{
22    round_down(value + granularity - T::one(), granularity)
23}
24
25// Returns a range within a range.
26// For example, subrange(100..200, 20..30) = 120..130.
27fn subrange<R: RangeBounds<usize>>(source: &Range<usize>, bounds: &R) -> Range<usize> {
28    let subrange = (match bounds.start_bound() {
29        Bound::Included(&s) => source.start + s,
30        Bound::Excluded(&s) => source.start + s + 1,
31        Bound::Unbounded => source.start,
32    })..(match bounds.end_bound() {
33        Bound::Included(&e) => source.start + e + 1,
34        Bound::Excluded(&e) => source.start + e,
35        Bound::Unbounded => source.end,
36    });
37    assert!(subrange.end <= source.end);
38    subrange
39}
40
41fn split_range(range: &Range<usize>, mid: usize) -> (Range<usize>, Range<usize>) {
42    let l = range.end - range.start;
43    let base = range.start;
44    (base..base + mid, base + mid..base + l)
45}
46
47// TODO(jfsulliv): Eventually we will want zero-copy buffers which are provided by filesystem
48// clients (e.g. via zx::stream) and which we either splice pages into or out of from a transfer
49// buffer, or which we directly connect to the block device, or which we read and write to in some
50// different way (involving changes to the block interface).
51
52/// Buffer is a read-write buffer that can be used for I/O with the block device. They are created
53/// by a BufferAllocator, and automatically deallocate themselves when they go out of scope.
54///
55/// Most usage will be on the unowned BufferRef and MutableBufferRef types, since these types are
56/// used for Device::read and Device::write.
57///
58/// Buffers are always block-aligned (both in offset and length), but unaligned slices can be made
59/// with the reference types. That said, the Device trait requires aligned BufferRef and
60/// MutableBufferRef objects, so alignment must be restored by the time a device read/write is
61/// requested.
62///
63/// For example, when writing an unaligned amount of data to the device, generally two Buffers
64/// would need to be involved; the input Buffer could be used to write everything up to the last
65/// block, and a second single-block alignment Buffer would be used to read-modify-update the last
66/// block.
67#[derive(Debug)]
68pub struct Buffer<'a>(MutableBufferRef<'a>);
69
70// Alias for the traits which need to be satisfied for |subslice| and friends.
71// This trait is automatically satisfied for most typical uses (a..b, a.., ..b, ..).
72pub trait SliceRange: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
73impl<T> SliceRange for T where T: Clone + RangeBounds<usize> + SliceIndex<[u8], Output = [u8]> {}
74
75impl<'a> Buffer<'a> {
76    pub(super) fn new(
77        slice: &'a mut [u8],
78        range: Range<usize>,
79        allocator: &'a BufferAllocator,
80    ) -> Self {
81        Self(MutableBufferRef { slice, range, allocator })
82    }
83
84    /// Takes a read-only reference to this buffer.
85    pub fn as_ref(&self) -> BufferRef<'_> {
86        self.subslice(..)
87    }
88
89    /// Takes a read-only reference to this buffer over |range| (which must be within the size of
90    /// the buffer).
91    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
92        self.0.subslice(range)
93    }
94
95    /// Takes a read-write reference to this buffer.
96    pub fn as_mut(&mut self) -> MutableBufferRef<'_> {
97        self.subslice_mut(..)
98    }
99
100    /// Takes a read-write reference to this buffer over |range| (which must be within the size of
101    /// the buffer).
102    pub fn subslice_mut<R: SliceRange>(&mut self, range: R) -> MutableBufferRef<'_> {
103        self.0.reborrow().subslice_mut(range)
104    }
105
106    /// Returns the buffer's capacity.
107    pub fn len(&self) -> usize {
108        self.0.len()
109    }
110
111    /// Returns a slice of the buffer's contents.
112    pub fn as_slice(&self) -> &[u8] {
113        self.0.as_slice()
114    }
115
116    /// Returns a mutable slice of the buffer's contents.
117    pub fn as_mut_slice(&mut self) -> &mut [u8] {
118        self.0.as_mut_slice()
119    }
120
121    /// Returns the range in the underlying BufferSource that this buffer covers.
122    pub fn range(&self) -> Range<usize> {
123        self.0.range()
124    }
125
126    /// Returns a reference to the allocator.
127    pub fn allocator(&self) -> &BufferAllocator {
128        self.0.allocator
129    }
130}
131
132impl<'a> Drop for Buffer<'a> {
133    fn drop(&mut self) {
134        self.0.allocator.free_buffer(self.range());
135    }
136}
137
138/// BufferRef is an unowned, read-only view over a Buffer.
139#[derive(Clone, Copy, Debug)]
140pub struct BufferRef<'a> {
141    slice: &'a [u8],
142    start: usize, // Not range so that we get Copy.
143    end: usize,
144    allocator: &'a BufferAllocator,
145}
146
147impl<'a> BufferRef<'a> {
148    /// Returns the buffer's capacity.
149    pub fn len(&self) -> usize {
150        self.end - self.start
151    }
152
153    pub fn is_empty(&self) -> bool {
154        self.end == self.start
155    }
156
157    /// Returns a slice of the buffer's contents.
158    pub fn as_slice(&self) -> &[u8] {
159        self.slice
160    }
161
162    /// Slices and consumes this reference. See Buffer::subslice.
163    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
164        let slice = &self.slice[range.clone()];
165        let range = subrange(&self.range(), &range);
166        BufferRef { slice, start: range.start, end: range.end, allocator: self.allocator }
167    }
168
169    /// Splits at |mid| (included in the right child), yielding two BufferRefs.
170    pub fn split_at(&self, mid: usize) -> (BufferRef<'_>, BufferRef<'_>) {
171        let slices = self.slice.split_at(mid);
172        let ranges = split_range(&self.range(), mid);
173        (
174            BufferRef {
175                slice: slices.0,
176                start: ranges.0.start,
177                end: ranges.0.end,
178                allocator: self.allocator,
179            },
180            BufferRef {
181                slice: slices.1,
182                start: ranges.1.start,
183                end: ranges.1.end,
184                allocator: self.allocator,
185            },
186        )
187    }
188
189    /// Returns the range in the underlying BufferSource that this BufferRef covers.
190    /// TODO(jfsulliv): Currently unused in host code. Remove when there is a real Device impl.
191    #[allow(dead_code)]
192    pub fn range(&self) -> Range<usize> {
193        self.start..self.end
194    }
195}
196
197/// MutableBufferRef is an unowned, read-write view of a Buffer.
198#[derive(Debug)]
199pub struct MutableBufferRef<'a> {
200    slice: &'a mut [u8],
201    range: Range<usize>,
202    allocator: &'a BufferAllocator,
203}
204
205impl<'a> MutableBufferRef<'a> {
206    /// Returns the buffer's capacity.
207    pub fn len(&self) -> usize {
208        self.range.end - self.range.start
209    }
210
211    pub fn is_empty(&self) -> bool {
212        self.range.end == self.range.start
213    }
214
215    pub fn as_ref(&self) -> BufferRef<'_> {
216        self.subslice(..)
217    }
218
219    pub fn into_ref(self) -> BufferRef<'a> {
220        BufferRef {
221            slice: self.slice,
222            start: self.range.start,
223            end: self.range.end,
224            allocator: self.allocator,
225        }
226    }
227
228    /// Returns a slice of the buffer's contents.
229    pub fn as_slice(&self) -> &[u8] {
230        self.slice
231    }
232
233    /// Returns a mutable slice of the buffer's contents.
234    pub fn as_mut_slice(&mut self) -> &mut [u8] {
235        self.slice
236    }
237
238    /// Reborrows this reference with a lesser lifetime. This mirrors the usual borrowing semantics
239    /// (i.e. the borrow ends when the new reference goes out of scope), and exists so that a
240    /// MutableBufferRef can be subsliced without consuming it.
241    ///
242    /// For example:
243    ///    let mut buf: MutableBufferRef<'_> = ...;
244    ///    {
245    ///        let sub = buf.reborrow().subslice_mut(a..b);
246    ///    }
247    pub fn reborrow(&mut self) -> MutableBufferRef<'_> {
248        MutableBufferRef { slice: self.slice, range: self.range.clone(), allocator: self.allocator }
249    }
250
251    /// Slices this reference. See Buffer::subslice.
252    pub fn subslice<R: SliceRange>(&self, range: R) -> BufferRef<'_> {
253        let slice = &self.slice[range.clone()];
254        let range = subrange(&self.range, &range);
255        BufferRef { slice, start: range.start, end: range.end, allocator: self.allocator }
256    }
257
258    /// Slices and consumes this reference. See Buffer::subslice_mut.
259    pub fn subslice_mut<R: SliceRange>(mut self, range: R) -> MutableBufferRef<'a> {
260        self.slice = &mut self.slice[range.clone()];
261        self.range = subrange(&self.range, &range);
262        self
263    }
264
265    /// Splits at |mid| (included in the right child), yielding two BufferRefs.
266    pub fn split_at(&self, mid: usize) -> (BufferRef<'_>, BufferRef<'_>) {
267        let slices = self.slice.split_at(mid);
268        let ranges = split_range(&self.range, mid);
269        (
270            BufferRef {
271                slice: slices.0,
272                start: ranges.0.start,
273                end: ranges.0.end,
274                allocator: self.allocator,
275            },
276            BufferRef {
277                slice: slices.1,
278                start: ranges.1.start,
279                end: ranges.1.end,
280                allocator: self.allocator,
281            },
282        )
283    }
284
285    /// Consumes the reference and splits it at |mid| (included in the right child), yielding two
286    /// MutableBufferRefs.
287    pub fn split_at_mut(self, mid: usize) -> (MutableBufferRef<'a>, MutableBufferRef<'a>) {
288        let slices = self.slice.split_at_mut(mid);
289        let ranges = split_range(&self.range, mid);
290        (
291            MutableBufferRef { slice: slices.0, range: ranges.0, allocator: self.allocator },
292            MutableBufferRef { slice: slices.1, range: ranges.1, allocator: self.allocator },
293        )
294    }
295
296    /// Returns the range in the underlying BufferSource that this MutableBufferRef covers.
297    /// TODO(jfsulliv): Currently unused in host code. Remove when there is a real Device impl.
298    #[allow(dead_code)]
299    pub fn range(&self) -> Range<usize> {
300        self.range.clone()
301    }
302}