1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::future::Future;
use std::io;

use compio::fs::File;
use compio::io::AsyncReadAtExt;
use compio::BufResult;
use vortex_buffer::Buffer;
use vortex_error::VortexUnwrap;

use crate::VortexReadAt;

impl VortexReadAt for File {
    fn read_byte_range(
        &self,
        pos: u64,
        len: u64,
    ) -> impl Future<Output = io::Result<Buffer>> + 'static {
        let this = self.clone();
        let buffer = Vec::with_capacity(len.try_into().vortex_unwrap());
        async move {
            // Turn the buffer into a static slice.
            let BufResult(res, buffer) = this.read_exact_at(buffer, pos).await;
            res.map(|_| Buffer::from(buffer))
        }
    }

    fn size(&self) -> impl Future<Output = io::Result<u64>> + 'static {
        let this = self.clone();
        async move { this.metadata().await.map(|metadata| metadata.len()) }
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;

    use compio::fs::File;
    use tempfile::NamedTempFile;

    use crate::VortexReadAt;

    #[cfg_attr(miri, ignore)]
    #[compio::test]
    async fn test_read_at_compio_file() {
        let mut tmpfile = NamedTempFile::new().unwrap();
        write!(tmpfile, "0123456789").unwrap();

        // Open up a file handle in compio land
        let file = File::open(tmpfile.path()).await.unwrap();

        // Use the file as a VortexReadAt instance.
        let read = file.read_byte_range(2, 4).await.unwrap();
        assert_eq!(read.as_ref(), "2345".as_bytes());
    }
}