disk_blob/blob/
file.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! File-backed blobs.
5
6use super::Blob;
7use async_trait::async_trait;
8use inspect::Inspect;
9use std::fs::File;
10use std::io;
11use std::sync::Arc;
12
13/// A blob backed by a local file.
14#[derive(Debug, Inspect)]
15pub struct FileBlob {
16    file: Arc<File>,
17    len: u64,
18}
19
20impl FileBlob {
21    /// Returns a new file blob for `file`.
22    pub fn new(file: File) -> io::Result<Self> {
23        let len = file.metadata()?.len();
24        Ok(Self {
25            file: Arc::new(file),
26            len,
27        })
28    }
29}
30
31#[async_trait]
32impl Blob for FileBlob {
33    async fn read(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
34        let file = self.file.clone();
35        let len = buf.len();
36        let data = blocking::unblock(move || {
37            let mut data = vec![0; len];
38            let n = file.read_at(&mut data, offset)?;
39            if n < data.len() {
40                return Err(io::ErrorKind::UnexpectedEof.into());
41            }
42            io::Result::Ok(data)
43        })
44        .await?;
45        buf.copy_from_slice(&data);
46        Ok(())
47    }
48
49    fn len(&self) -> u64 {
50        self.len
51    }
52}
53
54/// A unified extension trait for [`std::fs::File`] for reading at a
55/// given offset.
56///
57/// The semantics are slightly different between Windows and Unix--on Windows,
58/// each operation updates the current file pointer, whereas on Unix it does
59/// not.
60trait ReadAt {
61    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
62}
63
64#[cfg(windows)]
65impl ReadAt for File {
66    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
67        std::os::windows::fs::FileExt::seek_read(self, buf, offset)
68    }
69}
70
71#[cfg(unix)]
72impl ReadAt for File {
73    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
74        std::os::unix::fs::FileExt::read_at(self, buf, offset)
75    }
76}