mirror of
https://github.com/dswd/zvault
synced 2025-03-16 22:02:45 +00:00
107 lines
3.6 KiB
Rust
107 lines
3.6 KiB
Rust
|
use ::prelude::*;
|
||
|
|
||
|
use std::path::{Path, PathBuf};
|
||
|
use std::fs::{self, File};
|
||
|
use std::io::{self, BufReader, BufWriter, Write, Read};
|
||
|
|
||
|
|
||
|
pub static CACHE_FILE_STRING: [u8; 7] = *b"zvault\x04";
|
||
|
pub static CACHE_FILE_VERSION: u8 = 1;
|
||
|
|
||
|
|
||
|
quick_error!{
|
||
|
#[derive(Debug)]
|
||
|
pub enum BundleCacheError {
|
||
|
Read(err: io::Error) {
|
||
|
cause(err)
|
||
|
description("Failed to read bundle cache")
|
||
|
display("Bundle cache error: failed to read bundle cache\n\tcaused by: {}", err)
|
||
|
}
|
||
|
Write(err: io::Error) {
|
||
|
cause(err)
|
||
|
description("Failed to write bundle cache")
|
||
|
display("Bundle cache error: failed to write bundle cache\n\tcaused by: {}", err)
|
||
|
}
|
||
|
WrongHeader {
|
||
|
description("Wrong header")
|
||
|
display("Bundle cache error: wrong header on bundle cache")
|
||
|
}
|
||
|
UnsupportedVersion(version: u8) {
|
||
|
description("Wrong version")
|
||
|
display("Bundle cache error: unsupported version: {}", version)
|
||
|
}
|
||
|
Decode(err: msgpack::DecodeError) {
|
||
|
from()
|
||
|
cause(err)
|
||
|
description("Failed to decode bundle cache")
|
||
|
display("Bundle cache error: failed to decode bundle cache\n\tcaused by: {}", err)
|
||
|
}
|
||
|
Encode(err: msgpack::EncodeError) {
|
||
|
from()
|
||
|
cause(err)
|
||
|
description("Failed to encode bundle cache")
|
||
|
display("Bundle cache error: failed to encode bundle cache\n\tcaused by: {}", err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#[derive(Clone, Default)]
|
||
|
pub struct StoredBundle {
|
||
|
pub info: BundleInfo,
|
||
|
pub path: PathBuf
|
||
|
}
|
||
|
serde_impl!(StoredBundle(u64) {
|
||
|
info: BundleInfo => 0,
|
||
|
path: PathBuf => 1
|
||
|
});
|
||
|
|
||
|
impl StoredBundle {
|
||
|
#[inline]
|
||
|
pub fn id(&self) -> BundleId {
|
||
|
self.info.id.clone()
|
||
|
}
|
||
|
|
||
|
pub fn move_to<P: AsRef<Path>>(mut self, path: P) -> Result<Self, BundleDbError> {
|
||
|
let path = path.as_ref();
|
||
|
if fs::rename(&self.path, path).is_err() {
|
||
|
try!(fs::copy(&self.path, path).context(path));
|
||
|
try!(fs::remove_file(&self.path).context(&self.path as &Path));
|
||
|
}
|
||
|
self.path = path.to_path_buf();
|
||
|
Ok(self)
|
||
|
}
|
||
|
|
||
|
pub fn copy_to<P: AsRef<Path>>(&self, path: P) -> Result<Self, BundleDbError> {
|
||
|
let path = path.as_ref();
|
||
|
try!(fs::copy(&self.path, path).context(path));
|
||
|
let mut bundle = self.clone();
|
||
|
bundle.path = path.to_path_buf();
|
||
|
Ok(bundle)
|
||
|
}
|
||
|
|
||
|
pub fn read_list_from<P: AsRef<Path>>(path: P) -> Result<Vec<Self>, BundleCacheError> {
|
||
|
let path = path.as_ref();
|
||
|
let mut file = BufReader::new(try!(File::open(path).map_err(BundleCacheError::Read)));
|
||
|
let mut header = [0u8; 8];
|
||
|
try!(file.read_exact(&mut header).map_err(BundleCacheError::Read));
|
||
|
if header[..CACHE_FILE_STRING.len()] != CACHE_FILE_STRING {
|
||
|
return Err(BundleCacheError::WrongHeader)
|
||
|
}
|
||
|
let version = header[CACHE_FILE_STRING.len()];
|
||
|
if version != CACHE_FILE_VERSION {
|
||
|
return Err(BundleCacheError::UnsupportedVersion(version))
|
||
|
}
|
||
|
Ok(try!(msgpack::decode_from_stream(&mut file)))
|
||
|
}
|
||
|
|
||
|
pub fn save_list_to<P: AsRef<Path>>(list: &[Self], path: P) -> Result<(), BundleCacheError> {
|
||
|
let path = path.as_ref();
|
||
|
let mut file = BufWriter::new(try!(File::create(path).map_err(BundleCacheError::Write)));
|
||
|
try!(file.write_all(&CACHE_FILE_STRING).map_err(BundleCacheError::Write));
|
||
|
try!(file.write_all(&[CACHE_FILE_VERSION]).map_err(BundleCacheError::Write));
|
||
|
try!(msgpack::encode_to_stream(&list, &mut file));
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|