turbo_persistence/
arc_bytes.rs1use std::{
2 borrow::Borrow,
3 fmt::{self, Debug, Formatter},
4 hash::{Hash, Hasher},
5 ops::{Deref, Range},
6 sync::Arc,
7};
8
9use memmap2::Mmap;
10
11use crate::{
12 compression::decompress_into_arc,
13 shared_bytes::{SharedBytes, is_subslice_of},
14};
15#[derive(Clone)]
20enum Backing {
21 Arc { _backing: Arc<[u8]> },
22 Mmap { _backing: Arc<Mmap> },
23}
24
25#[derive(Clone)]
27pub struct ArcBytes {
28 data: *const [u8],
29 backing: Backing,
33}
34
35unsafe impl Send for ArcBytes {}
36unsafe impl Sync for ArcBytes {}
37
38impl From<Arc<[u8]>> for ArcBytes {
39 fn from(arc: Arc<[u8]>) -> Self {
40 Self {
41 data: &*arc as *const [u8],
42 backing: Backing::Arc { _backing: arc },
43 }
44 }
45}
46
47impl From<Box<[u8]>> for ArcBytes {
48 fn from(b: Box<[u8]>) -> Self {
49 Self::from(Arc::from(b))
50 }
51}
52
53impl Deref for ArcBytes {
54 type Target = [u8];
55
56 fn deref(&self) -> &Self::Target {
57 unsafe { &*self.data }
58 }
59}
60
61impl Borrow<[u8]> for ArcBytes {
62 fn borrow(&self) -> &[u8] {
63 self
64 }
65}
66
67impl Hash for ArcBytes {
68 fn hash<H: Hasher>(&self, state: &mut H) {
69 self.deref().hash(state)
70 }
71}
72
73impl PartialEq for ArcBytes {
74 fn eq(&self, other: &Self) -> bool {
75 self.deref().eq(other.deref())
76 }
77}
78
79impl Debug for ArcBytes {
80 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
81 Debug::fmt(&**self, f)
82 }
83}
84
85impl Eq for ArcBytes {}
86
87impl ArcBytes {
88 pub fn is_mmap_backed(&self) -> bool {
90 matches!(self.backing, Backing::Mmap { .. })
91 }
92
93 pub fn is_shared_arc(&self) -> bool {
98 match &self.backing {
99 Backing::Arc { _backing } => Arc::strong_count(_backing) > 1,
100 Backing::Mmap { .. } => false,
101 }
102 }
103}
104
105impl SharedBytes for ArcBytes {
106 type MmapHandle = Arc<Mmap>;
107
108 fn slice(self, range: Range<usize>) -> Self {
109 let data = &*self;
110 let data = &data[range] as *const [u8];
111 Self {
112 data,
113 backing: self.backing,
114 }
115 }
116
117 unsafe fn slice_from_subslice(&self, subslice: &[u8]) -> Self {
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 unsafe fn from_mmap(mmap: &Arc<Mmap>, subslice: &[u8]) -> Self {
135 debug_assert!(
136 is_subslice_of(subslice, mmap),
137 "from_mmap: subslice is not within the mmap"
138 );
139 ArcBytes {
140 data: subslice as *const [u8],
141 backing: Backing::Mmap {
142 _backing: mmap.clone(),
143 },
144 }
145 }
146
147 fn from_decompressed(uncompressed_length: u32, block: &[u8]) -> anyhow::Result<Self> {
148 Ok(ArcBytes::from(decompress_into_arc(
149 uncompressed_length,
150 block,
151 )?))
152 }
153}