Line data Source code
1 : use std::{
2 : ops::{Deref, Range, RangeBounds},
3 : sync::Arc,
4 : };
5 :
6 : use super::{alignment::Alignment, raw::RawAlignedBuffer};
7 :
8 : /// An shared, immutable aligned buffer type.
9 : pub struct AlignedBuffer<A: Alignment> {
10 : /// Shared raw buffer.
11 : raw: Arc<RawAlignedBuffer<A>>,
12 : /// Range that specifies the current slice.
13 : range: Range<usize>,
14 : }
15 :
16 : impl<A: Alignment> AlignedBuffer<A> {
17 : /// Creates an immutable `IoBuffer` from the raw buffer
18 968 : pub(super) fn from_raw(raw: RawAlignedBuffer<A>, range: Range<usize>) -> Self {
19 968 : AlignedBuffer {
20 968 : raw: Arc::new(raw),
21 968 : range,
22 968 : }
23 968 : }
24 :
25 : /// Returns the number of bytes in the buffer, also referred to as its 'length'.
26 : #[inline]
27 70184595 : pub fn len(&self) -> usize {
28 70184595 : self.range.len()
29 70184595 : }
30 :
31 : /// Returns the alignment of the buffer.
32 : #[inline]
33 0 : pub fn align(&self) -> usize {
34 0 : self.raw.align()
35 0 : }
36 :
37 : #[inline]
38 30714949 : fn as_ptr(&self) -> *const u8 {
39 30714949 : // SAFETY: `self.range.start` is guaranteed to be within [0, self.len()).
40 30714949 : unsafe { self.raw.as_ptr().add(self.range.start) }
41 30714949 : }
42 :
43 : /// Extracts a slice containing the entire buffer.
44 : ///
45 : /// Equivalent to `&s[..]`.
46 : #[inline]
47 0 : fn as_slice(&self) -> &[u8] {
48 0 : &self.raw.as_slice()[self.range.start..self.range.end]
49 0 : }
50 :
51 : /// Returns a slice of self for the index range `[begin..end)`.
52 4385516 : pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
53 : use core::ops::Bound;
54 4385516 : let len = self.len();
55 :
56 4385516 : let begin = match range.start_bound() {
57 4385516 : Bound::Included(&n) => n,
58 0 : Bound::Excluded(&n) => n.checked_add(1).expect("out of range"),
59 0 : Bound::Unbounded => 0,
60 : };
61 :
62 4385516 : let end = match range.end_bound() {
63 0 : Bound::Included(&n) => n.checked_add(1).expect("out of range"),
64 4385516 : Bound::Excluded(&n) => n,
65 0 : Bound::Unbounded => len,
66 : };
67 :
68 4385516 : assert!(
69 4385516 : begin <= end,
70 0 : "range start must not be greater than end: {:?} <= {:?}",
71 : begin,
72 : end,
73 : );
74 4385516 : assert!(
75 4385516 : end <= len,
76 0 : "range end out of bounds: {:?} <= {:?}",
77 : end,
78 : len,
79 : );
80 :
81 4385516 : let begin = self.range.start + begin;
82 4385516 : let end = self.range.start + end;
83 4385516 :
84 4385516 : AlignedBuffer {
85 4385516 : raw: Arc::clone(&self.raw),
86 4385516 : range: begin..end,
87 4385516 : }
88 4385516 : }
89 : }
90 :
91 : impl<A: Alignment> Deref for AlignedBuffer<A> {
92 : type Target = [u8];
93 :
94 0 : fn deref(&self) -> &Self::Target {
95 0 : self.as_slice()
96 0 : }
97 : }
98 :
99 : impl<A: Alignment> AsRef<[u8]> for AlignedBuffer<A> {
100 0 : fn as_ref(&self) -> &[u8] {
101 0 : self.as_slice()
102 0 : }
103 : }
104 :
105 : impl<A: Alignment> PartialEq<[u8]> for AlignedBuffer<A> {
106 0 : fn eq(&self, other: &[u8]) -> bool {
107 0 : self.as_slice().eq(other)
108 0 : }
109 : }
110 :
111 : /// SAFETY: the underlying buffer references a stable memory region.
112 : unsafe impl<A: Alignment> tokio_epoll_uring::IoBuf for AlignedBuffer<A> {
113 30714949 : fn stable_ptr(&self) -> *const u8 {
114 30714949 : self.as_ptr()
115 30714949 : }
116 :
117 48257015 : fn bytes_init(&self) -> usize {
118 48257015 : self.len()
119 48257015 : }
120 :
121 13156548 : fn bytes_total(&self) -> usize {
122 13156548 : self.len()
123 13156548 : }
124 : }
|