Implement some persistency features

This commit is contained in:
2019-04-30 19:08:40 +02:00
parent 450ecbccad
commit 39b2a2c442
4 changed files with 113 additions and 17 deletions

View File

@ -0,0 +1,18 @@
use crate::model::Texture;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io;
use std::path::Path;
#[derive(Deserialize, Serialize)]
struct CollectionFile {
textures: Vec<Texture>,
}
pub fn load_collection_file(path: &Path) -> io::Result<Vec<Texture>> {
let file = fs::File::open(path)?;
let buf_reader = io::BufReader::new(file);
let collection: CollectionFile = serde_json::from_reader(buf_reader)?;
Ok(collection.textures)
}

View File

@ -6,11 +6,13 @@
use crate::model::*;
use std::collections::HashMap;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::Arc;
pub use self::search::Query;
mod collection_file;
mod image_convert;
mod search;
@ -31,7 +33,15 @@ pub struct DataStore {
impl DataStore {
pub fn new(path: &Path) -> io::Result<DataStore> {
unimplemented!()
let base_path = path.to_path_buf();
let mut collection_file_path = base_path.clone();
collection_file_path.push("collection.json");
Ok(DataStore {
data_dir: base_path,
texture: collection_file::load_collection_file(&collection_file_path)?,
preview_cache: HashMap::new(),
})
}
pub fn garbage_collect(&mut self) -> io::Result<()> {
@ -45,27 +55,86 @@ impl DataStore {
/// returns true if successful
pub fn delete(&mut self, tex: &Texture) -> bool {
unimplemented!();
// Find the texture
let pos = self.texture.iter().position(|e| e == tex);
match pos {
// Remove it
Some(idx) => {
let removed = self.texture.remove(idx);
let key = (removed.format, removed.texture_hash);
self.preview_cache.remove(&key);
true
}
// Texture not found
None => false,
}
}
pub fn insert(&mut self, tex: Texture) -> bool {
unimplemented!();
// Check for collisions
let pos = self
.texture
.iter()
.position(|e| e.id == tex.id || e.name == tex.name);
match pos {
// Texture with same name or id is already stored
Some(_) => false,
// Insert it
None => {
self.texture.push(tex);
true
}
}
}
pub fn by_name<'a>(&'a self, name: &str) -> Option<&'a Texture> {
unimplemented!();
let pos = self.texture.iter().position(|e| e.name == name);
match pos {
Some(idx) => Some(self.texture.get(idx).unwrap()),
None => None,
}
}
pub fn by_id<'a, 'b>(&'a self, id: &'b str) -> Option<&'a Texture> {
unimplemented!();
let pos = self.texture.iter().position(|e| e.id == id);
match pos {
Some(idx) => Some(self.texture.get(idx).unwrap()),
None => None,
}
}
pub fn has_hash(&self, hash: &Sha256) -> bool {
unimplemented!();
// TODO What is the purpose of this function?
// Currently checks for textures in the list with the given hash.
// Should it check for an existing image file instead?
self.texture
.iter()
.position(|e| &e.texture_hash == hash)
.is_some()
}
pub fn get_texture_file(&mut self, hash: &Sha256) -> TextureFileResult {
unimplemented!();
use io::Read;
let mut file_path = self.data_dir.clone();
file_path.push("textures");
file_path.push(hash.create_hex_string().to_lowercase());
let mut file = match fs::File::open(file_path) {
Ok(f) => f,
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
return Err(TextureFileError::NotFound);
} else {
return Err(TextureFileError::IoError(e));
}
}
};
let mut buffer = Vec::new();
match file.read_to_end(&mut buffer) {
Ok(_) => (),
Err(e) => return Err(TextureFileError::IoError(e)),
};
Ok(Arc::new(buffer))
}
pub fn get_texture_preview(&mut self, hash: &Sha256) -> TextureFileResult {