tdb_succinct/storage/
file.rs1use std::io::SeekFrom;
2use std::path::PathBuf;
3
4use async_trait::async_trait;
5use bytes::{Bytes, BytesMut};
6use tokio::fs::File;
7use tokio::io::{self, AsyncReadExt, AsyncSeekExt, BufWriter};
8
9use super::{FileLoad, FileStore, SyncableFile};
10
11#[derive(Clone, Debug)]
12pub struct FileBackedStore {
13 path: PathBuf,
14}
15
16#[async_trait]
17impl SyncableFile for File {
18 async fn sync_all(self) -> io::Result<()> {
19 File::sync_all(&self).await
20 }
21}
22
23#[async_trait]
24impl SyncableFile for BufWriter<File> {
25 async fn sync_all(self) -> io::Result<()> {
26 let inner = self.into_inner();
27
28 File::sync_all(&inner).await
29 }
30}
31
32impl FileBackedStore {
33 pub fn new<P: Into<PathBuf>>(path: P) -> FileBackedStore {
34 FileBackedStore { path: path.into() }
35 }
36}
37
38#[async_trait]
39impl FileLoad for FileBackedStore {
40 type Read = File;
41
42 async fn exists(&self) -> io::Result<bool> {
43 let metadata = tokio::fs::metadata(&self.path).await;
44 Ok(!(metadata.is_err() && metadata.err().unwrap().kind() == io::ErrorKind::NotFound))
45 }
46
47 async fn size(&self) -> io::Result<usize> {
48 let m = tokio::fs::metadata(&self.path).await?;
49 Ok(m.len() as usize)
50 }
51
52 async fn open_read_from(&self, offset: usize) -> io::Result<File> {
53 let mut options = tokio::fs::OpenOptions::new();
54 options.read(true);
55 let mut file = options.open(&self.path).await?;
56
57 file.seek(SeekFrom::Start(offset as u64)).await?;
58
59 Ok(file)
60 }
61
62 async fn map(&self) -> io::Result<Bytes> {
63 let size = self.size().await?;
64 if size == 0 {
65 Ok(Bytes::new())
66 } else {
67 let mut f = self.open_read().await?;
68 let mut b = BytesMut::with_capacity(size);
69
70 unsafe { b.set_len(size) };
78 f.read_exact(&mut b[..]).await?;
79 Ok(b.freeze())
80 }
81 }
82}
83
84#[async_trait]
85impl FileStore for FileBackedStore {
86 type Write = BufWriter<File>;
87
88 async fn open_write(&self) -> io::Result<BufWriter<File>> {
89 let mut options = tokio::fs::OpenOptions::new();
90 options.read(true).write(true).create(true);
91 let file = options.open(&self.path).await?;
92
93 Ok(BufWriter::new(file))
94 }
95}