simple_disk_cache/
config.rs

1use bincode;
2use serde_json;
3use std::io::{self, Read, Write};
4use serde::Serialize;
5use serde::de::DeserializeOwned;
6
7/// General configuration of the cache functionality.
8#[derive(Clone, Debug)]
9pub struct CacheConfig {
10    /// Maximum size of the cache in bytes.
11    pub max_bytes: u64,
12
13    /// Encoding format of the data files.
14    pub encoding: DataEncoding,
15
16    /// Strategy of the cache used.
17    pub strategy: CacheStrategy,
18
19    /// Number of subdirectories per level. (There are two levels.)
20    pub subdirs_per_level: u32,
21}
22
23#[derive(Clone, Debug)]
24pub enum DataEncoding {
25    Bincode,
26    Json,
27}
28
29impl DataEncoding {
30    pub(crate) fn extension(&self) -> &'static str {
31        match *self {
32            DataEncoding::Bincode => "bincode",
33            DataEncoding::Json => "json",
34        }
35    }
36
37    pub(crate) fn serialize<T: Serialize, W: Write>(
38        &self,
39        writer: &mut W,
40        value: &T,
41    ) -> Result<usize, SerializeError> {
42        // TODO: This could probably be improved by a lot if we could actually write
43        // directly into the Write instead of first into a vec. Both the bincode and serde_json
44        // crate offer such method, but neither reports the bytes written. It should be evaluated
45        // if a simple wrapper struct for Write which counts the bytes written is more performant
46        // than serializing to a Vec<u8> first.
47
48        let bytes = match *self {
49            DataEncoding::Bincode => {
50                bincode::serialize(value).map_err(|e| SerializeError::Bincode(e))?
51            }
52            DataEncoding::Json => serde_json::to_vec(value).map_err(|e| SerializeError::Json(e))?,
53        };
54        let len = bytes.len();
55        writer
56            .write(&bytes[..])
57            .map_err(|e| SerializeError::WriteError(e))?;
58        Ok(len)
59    }
60
61    pub(crate) fn deserialize<T: DeserializeOwned, R: Read>(
62        &self,
63        reader: R,
64    ) -> Result<T, DeserializeError> {
65        match *self {
66            DataEncoding::Bincode => {
67                bincode::deserialize_from(reader).map_err(|e| DeserializeError::Bincode(e))
68            }
69            DataEncoding::Json => {
70                serde_json::from_reader(reader).map_err(|e| DeserializeError::Json(e))
71            }
72        }
73    }
74}
75
76#[derive(Debug, Fail)]
77pub enum SerializeError {
78    #[fail(display = "Failed serializing to bincode: {:?}", _0)]
79    Bincode(bincode::Error),
80
81    #[fail(display = "Failed serializing to json: {:?}", _0)]
82    Json(serde_json::Error),
83
84    #[fail(display = "Writing to file failed: {:?}", _0)]
85    WriteError(io::Error),
86}
87
88#[derive(Debug, Fail)]
89pub enum DeserializeError {
90    #[fail(display = "Failed deserializing bincode: {:?}", _0)]
91    Bincode(bincode::Error),
92
93    #[fail(display = "Failed deserializing json: {:?}", _0)]
94    Json(serde_json::Error),
95}
96
97#[derive(Clone, Debug)]
98pub enum CacheStrategy {
99    /// Least recently used.
100    ///
101    /// Delete the value that was least recently used when needed.
102    /// This is a good trade off keeping active values around and
103    /// deleting old ones to make room for new ones.
104    LRU,
105}
106
107impl Default for CacheStrategy {
108    fn default() -> Self {
109        CacheStrategy::LRU
110    }
111}