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
56
57
58
//! The [Vfs] trait is responsible for converting string keys to [Read] implementations.
//!
//! The cache caches the bytes representation from whatever the [Vfs] returns, then uses a [Decoder] on it when needed
//! to get the actual object.
use std::io::{Error, Read, Seek};

/// "open" a "file" and return a [VfsReader] over it.
///
/// This is the first step of the decoding process, and is used to get from a string key to a reader over some bytes to
/// pass to the [Decoder].
pub trait Vfs: Send + Sync + 'static {
    type Reader: VfsReader;

    /// Open a file.
    fn open(&self, key: &str) -> Result<Self::Reader, Error>;
}

/// A reader returned from the VFS.
///
/// Readers should handle closing in their drop implementations.
pub trait VfsReader: Read + Seek + Send + Sync + 'static {
    /// Return the size of this object once read.
    ///
    /// This function should try to be as inexpensive as possible.
    fn get_size(&self) -> Result<u64, Error>;
}

/// A `Decoder` knows how to get from a reader to a decoded representation in memory.
///
/// The output type must be sync in order to enable the cache to store elements behind `Arc`.
///
/// This crate does not insert a [std::io::BufReader] for you.  You should do so yourself as needed.
pub trait Decoder {
    type Output: Send + Sync;
    type Error: std::error::Error;

    fn decode<R: Read + Seek>(&self, reader: R) -> Result<Self::Output, Self::Error>;

    /// Estimate the cost of a decoded item, usually the in-memory size.
    fn estimate_cost(&self, item: &Self::Output) -> Result<u64, Self::Error>;

    /// Sometimes it is possible for the cache to directly provide bytes.  Implement this optional method to take
    /// advantage of that case.
    ///
    /// By default this just forwards to the `read` function.  Useful because some decoders are faster if they can be
    /// fed a slice of bytes, for example serde_json.
    fn decode_bytes(&self, bytes: &[u8]) -> Result<Self::Output, Self::Error> {
        self.decode(std::io::Cursor::new(bytes))
    }
}

impl<T: Vfs> Vfs for std::sync::Arc<T> {
    type Reader = T::Reader;

    fn open(&self, key: &str) -> Result<Self::Reader, Error> {
        (**self).open(key)
    }
}