indexlake_storage_fs/
file.rs1use std::{io::SeekFrom, ops::Range};
2
3use bytes::Bytes;
4use indexlake::{
5 ILError, ILResult,
6 storage::{FileMetadata, InputFile, OutputFile},
7};
8use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt};
9
10use crate::parse_std_fs_metadata;
11
12#[derive(Debug)]
13pub struct LocalInputFile {
14 pub file: tokio::fs::File,
15 pub relative_path: String,
16}
17
18#[async_trait::async_trait]
19impl InputFile for LocalInputFile {
20 async fn metadata(&self) -> ILResult<FileMetadata> {
21 let metadata = self
22 .file
23 .metadata()
24 .await
25 .map_err(|e| ILError::storage(format!("Failed to get file metadata: {e}")))?;
26 Ok(parse_std_fs_metadata(&metadata))
27 }
28
29 async fn read(&mut self, range: Range<u64>) -> ILResult<Bytes> {
30 self.file
31 .seek(SeekFrom::Start(range.start))
32 .await
33 .map_err(|e| {
34 ILError::storage(format!("Failed to seek file {}: {e}", self.relative_path))
35 })?;
36 let mut buffer = vec![0; (range.end - range.start) as usize];
37 self.file.read_exact(&mut buffer).await.map_err(|e| {
38 ILError::storage(format!("Failed to read file {}: {e}", self.relative_path))
39 })?;
40 Ok(Bytes::from(buffer))
41 }
42}
43
44#[derive(Debug)]
45pub struct LocalOutputFile {
46 pub file: tokio::fs::File,
47 pub relative_path: String,
48}
49
50#[async_trait::async_trait]
51impl OutputFile for LocalOutputFile {
52 async fn write(&mut self, data: Bytes) -> ILResult<()> {
53 self.file.write(&data).await.map_err(|e| {
54 ILError::storage(format!("Failed to write file {}: {e}", self.relative_path))
55 })?;
56 Ok(())
57 }
58
59 async fn close(&mut self) -> ILResult<()> {
60 self.file.flush().await.map_err(|e| {
61 ILError::storage(format!("Failed to flush file {}: {e}", self.relative_path))
62 })?;
63 Ok(())
64 }
65}