Merge branch 'master' of git.mosad.xyz:localhorst/TextureSync
This commit is contained in:
commit
cd8a3218d5
|
@ -1,20 +1,29 @@
|
|||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, Hash, PartialEq)]
|
||||
pub struct Sha256(#[serde(serialize_with = "as_hex", deserialize_with = "from_hex")] pub [u8; 32]);
|
||||
|
||||
fn hash_to_hex_string(hash: &[u8; 32]) -> String {
|
||||
use std::fmt::*;
|
||||
|
||||
let mut hex_string = String::with_capacity(64);
|
||||
for digit in hash.iter() {
|
||||
write!(hex_string, "{:02X}", digit).unwrap();
|
||||
}
|
||||
hex_string
|
||||
}
|
||||
|
||||
impl Sha256 {
|
||||
pub fn create_hex_string(&self) -> String {
|
||||
hash_to_hex_string(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_hex<S>(hash: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
use std::fmt::*;
|
||||
|
||||
let mut hex_string = String::new();
|
||||
for digit in hash {
|
||||
write!(hex_string, "{:02X}", digit).unwrap();
|
||||
}
|
||||
|
||||
serializer.serialize_str(&hex_string)
|
||||
serializer.serialize_str(&hash_to_hex_string(hash))
|
||||
}
|
||||
|
||||
fn from_hex<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, Eq, Hash, PartialEq)]
|
||||
pub enum TextureFormat {
|
||||
#[serde(rename = "png")]
|
||||
PNG,
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue