diff options
Diffstat (limited to 'src/cache.rs')
-rw-r--r-- | src/cache.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/cache.rs b/src/cache.rs new file mode 100644 index 0000000..f64b45a --- /dev/null +++ b/src/cache.rs @@ -0,0 +1,78 @@ +//! Caching support to prevent hitting the API a lot. +use std::fs::File; +use std::io::prelude::*; +use std::path::Path; + +use xdg::BaseDirectories; + +use super::APP_NAME; + +quick_error! { + #[derive(Debug)] + pub enum CacheError { + Io(err: std::io::Error) { + cause(err) + from() + } + } +} + +/// A generic cache. +pub trait Cache { + fn store(&mut self, path: &Path, data: &[u8]) -> Result<(), CacheError>; + fn get(&mut self, path: &Path) -> Result<Option<Vec<u8>>, CacheError>; +} + +/// A cache that stores files in the XDG specified cache location. +pub struct FileCache { + dirs: BaseDirectories, +} + +impl FileCache { + /// Create a new file backed cache. + pub fn new() -> Self { + let dirs = BaseDirectories::with_prefix(APP_NAME).unwrap(); + FileCache { dirs } + } +} + +impl Cache for FileCache { + fn store(&mut self, path: &Path, data: &[u8]) -> Result<(), CacheError> { + let cache_path = self.dirs.place_cache_file(path).unwrap(); + let mut f = File::create(cache_path)?; + f.write_all(data)?; + Ok(()) + } + + fn get(&mut self, path: &Path) -> Result<Option<Vec<u8>>, CacheError> { + let cache_path = self.dirs.find_cache_file(path); + match cache_path { + Some(p) => { + let mut f = File::open(p)?; + let mut buffer = Vec::new(); + f.read_to_end(&mut buffer)?; + Ok(Some(buffer)) + } + None => Ok(None), + } + } +} + +/// A cache that does nothing. +struct NoopCache; + +impl NoopCache { + pub fn new() -> Self { + NoopCache + } +} + +impl Cache for NoopCache { + fn store(&mut self, _path: &Path, _data: &[u8]) -> Result<(), CacheError> { + Ok(()) + } + + fn get(&mut self, _path: &Path) -> Result<Option<Vec<u8>>, CacheError> { + Ok(None) + } +} |