turbo_persistence/
arc_bytes.rs1use std::{
2 borrow::Borrow,
3 fmt::{self, Debug, Formatter},
4 hash::{Hash, Hasher},
5 io::{self, Read},
6 ops::{Deref, Range},
7 sync::Arc,
8};
9
10use memmap2::Mmap;
11
12#[derive(Clone)]
17enum Backing {
18 Arc { _backing: Arc<[u8]> },
19 Mmap { _backing: Arc<Mmap> },
20}
21
22#[derive(Clone)]
24pub struct ArcBytes {
25 data: *const [u8],
26 backing: Backing,
27}
28
29unsafe impl Send for ArcBytes {}
30unsafe impl Sync for ArcBytes {}
31
32impl From<Arc<[u8]>> for ArcBytes {
33 fn from(arc: Arc<[u8]>) -> Self {
34 Self {
35 data: &*arc as *const [u8],
36 backing: Backing::Arc { _backing: arc },
37 }
38 }
39}
40
41impl From<Box<[u8]>> for ArcBytes {
42 fn from(b: Box<[u8]>) -> Self {
43 Self::from(Arc::from(b))
44 }
45}
46
47impl Deref for ArcBytes {
48 type Target = [u8];
49
50 fn deref(&self) -> &Self::Target {
51 unsafe { &*self.data }
52 }
53}
54
55impl Borrow<[u8]> for ArcBytes {
56 fn borrow(&self) -> &[u8] {
57 self
58 }
59}
60
61impl Hash for ArcBytes {
62 fn hash<H: Hasher>(&self, state: &mut H) {
63 self.deref().hash(state)
64 }
65}
66
67impl PartialEq for ArcBytes {
68 fn eq(&self, other: &Self) -> bool {
69 self.deref().eq(other.deref())
70 }
71}
72
73impl Debug for ArcBytes {
74 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
75 Debug::fmt(&**self, f)
76 }
77}
78
79impl Eq for ArcBytes {}
80
81impl Read for ArcBytes {
82 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
83 let available = &**self;
84 let len = std::cmp::min(buf.len(), available.len());
85 buf[..len].copy_from_slice(&available[..len]);
86 self.data = &available[len..] as *const [u8];
88 Ok(len)
89 }
90}
91
92fn is_subslice_of(subslice: &[u8], backing: &[u8]) -> bool {
94 let backing = backing.as_ptr_range();
95 let sub = subslice.as_ptr_range();
96 sub.start >= backing.start && sub.end <= backing.end
97}
98
99impl ArcBytes {
100 pub fn slice(self, range: Range<usize>) -> ArcBytes {
102 let data = &*self;
103 let data = &data[range] as *const [u8];
104 Self {
105 data,
106 backing: self.backing,
107 }
108 }
109
110 pub unsafe fn slice_from_subslice(&self, subslice: &[u8]) -> ArcBytes {
118 debug_assert!(
119 is_subslice_of(
120 subslice,
121 match &self.backing {
122 Backing::Arc { _backing } => _backing,
123 Backing::Mmap { _backing } => _backing,
124 }
125 ),
126 "slice_from_subslice: subslice is not within the backing storage"
127 );
128 Self {
129 data: subslice as *const [u8],
130 backing: self.backing.clone(),
131 }
132 }
133
134 pub unsafe fn from_mmap(mmap: Arc<Mmap>, subslice: &[u8]) -> ArcBytes {
140 debug_assert!(
141 is_subslice_of(subslice, &mmap),
142 "from_mmap: subslice is not within the mmap"
143 );
144 ArcBytes {
145 data: subslice as *const [u8],
146 backing: Backing::Mmap { _backing: mmap },
147 }
148 }
149
150 pub fn is_mmap_backed(&self) -> bool {
152 matches!(self.backing, Backing::Mmap { .. })
153 }
154}