1use std::{
2 fmt::{self, Debug, Formatter},
3 io,
4 ops::Range,
5 sync::Arc,
6};
7
8use async_trait::async_trait;
9use block_on_place::HandleExt;
10use tantivy::{
11 HasLen,
12 directory::{FileHandle, OwnedBytes},
13};
14use tokio::runtime::Handle;
15
16use crate::{context::Context, operator::Operator};
17
18#[derive(Clone)]
29pub struct File {
30 path: String,
33
34 backend: Backend,
36}
37
38#[derive(Clone)]
40enum Backend {
41 Remote {
47 rt: Handle,
48
49 operator: Operator,
51
52 offset: u64,
54
55 len: u64,
57
58 chunks: Option<usize>,
60
61 concurrency: Option<usize>,
64 },
65
66 Memory { bytes: OwnedBytes },
74}
75
76impl File {
77 pub(crate) fn open(
82 path: impl Into<String>,
83 len: u64,
84 rt: Handle,
85 operator: Operator,
86 context: &Context,
87 ) -> Arc<Self> {
88 Arc::new(Self {
89 path: path.into(),
90 backend: Backend::Remote {
91 rt,
92 operator,
93 offset: 0,
94 len,
95 chunks: context.read_chunks,
96 concurrency: context.read_concurrency,
97 },
98 })
99 }
100
101 pub(crate) fn bundled(
106 path: impl Into<String>,
107 offset: u64,
108 len: u64,
109 rt: Handle,
110 operator: Operator,
111 context: &Context,
112 ) -> Arc<Self> {
113 Arc::new(Self {
114 path: path.into(),
115 backend: Backend::Remote {
116 rt,
117 operator,
118 offset,
119 len,
120 chunks: context.read_chunks,
121 concurrency: context.read_concurrency,
122 },
123 })
124 }
125
126 pub(crate) fn memory(path: impl Into<String>, bytes: &'static [u8]) -> Arc<Self> {
131 Arc::new(Self {
132 path: path.into(),
133 backend: Backend::Memory {
134 bytes: OwnedBytes::new(bytes),
135 },
136 })
137 }
138
139 pub(crate) fn memory_owned(path: impl Into<String>, bytes: Vec<u8>) -> Arc<Self> {
145 Arc::new(Self {
146 path: path.into(),
147 backend: Backend::Memory {
148 bytes: OwnedBytes::new(bytes),
149 },
150 })
151 }
152
153 #[inline]
155 pub fn path(&self) -> &str {
156 &self.path
157 }
158}
159
160#[async_trait]
161impl FileHandle for File {
162 fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
163 match &self.backend {
164 Backend::Remote { rt, .. } => rt.block_on_place(self.read_bytes_async(range)),
165 Backend::Memory { bytes } => Ok(bytes.slice(range)),
166 }
167 }
168
169 async fn read_bytes_async(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
170 let (operator, offset, chunks, concurrency) = match &self.backend {
171 Backend::Remote {
172 operator,
173 offset,
174 chunks,
175 concurrency,
176 ..
177 } => (operator, *offset, chunks, concurrency),
178
179 Backend::Memory { bytes } => return Ok(bytes.slice(range)),
181 };
182
183 let mut reader = operator.reader_with(&self.path);
184 if let Some(chunks) = chunks {
185 reader = reader.chunk(*chunks);
186 }
187
188 if let Some(concurrency) = concurrency {
189 reader = reader.concurrent(*concurrency);
190 }
191
192 let reader = reader.await.map_err(io::Error::other)?;
193 let range = Range {
196 start: offset + range.start as u64,
197 end: offset + range.end as u64,
198 };
199
200 let buffer = reader.read(range).await.map_err(io::Error::other)?;
201 let bytes = buffer.to_vec();
203 let bytes = OwnedBytes::new(bytes);
204
205 Ok(bytes)
206 }
207}
208
209impl HasLen for File {
210 fn len(&self) -> usize {
211 match &self.backend {
212 Backend::Remote { len, .. } => *len as usize,
213 Backend::Memory { bytes } => bytes.len(),
214 }
215 }
216}
217
218impl Debug for File {
219 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
220 let mut f = f.debug_struct("File");
221 f.field("path", &self.path);
222
223 match &self.backend {
224 Backend::Remote { offset, len, .. } => f.field("offset", offset).field("len", len),
225 Backend::Memory { bytes } => f.field("memory_len", &bytes.len()),
226 };
227
228 f.finish()
229 }
230}
231
232pub(crate) struct Slice {
241 inner: Arc<dyn FileHandle>,
242 offset: usize,
243 len: usize,
244}
245
246impl Slice {
247 pub fn new(inner: Arc<dyn FileHandle>, offset: usize, len: usize) -> Arc<Self> {
249 Arc::new(Self { inner, offset, len })
250 }
251}
252
253#[async_trait]
254impl FileHandle for Slice {
255 fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
256 self.inner
257 .read_bytes(self.offset + range.start..self.offset + range.end)
258 }
259
260 async fn read_bytes_async(&self, range: Range<usize>) -> io::Result<OwnedBytes> {
261 self.inner
262 .read_bytes_async(self.offset + range.start..self.offset + range.end)
263 .await
264 }
265}
266
267impl HasLen for Slice {
268 fn len(&self) -> usize {
269 self.len
270 }
271}
272
273impl Debug for Slice {
274 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
275 f.debug_struct("Slice")
276 .field("offset", &self.offset)
277 .field("len", &self.len)
278 .finish()
279 }
280}