use chrono::prelude::*; use serde::{Deserialize, Serialize}; use serde_json; use std::io::{Read, Write}; use std::path::PathBuf; use super::{ReadFileError, WriteFileError}; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct FileInfo { pub size: usize, pub created: DateTime, pub file_type: String, pub hash: String, } impl FileInfo { pub fn load(path: PathBuf) -> Result { let mut content: Vec = Vec::new(); let mut file = std::fs::File::open(path)?; file.read_to_end(&mut content)?; let js = serde_json::from_slice(&content)?; Ok(js) } pub fn save(&self, path: PathBuf) -> Result<(), WriteFileError> { let ser = serde_json::to_string(self).unwrap(); let mut file = std::fs::File::create(path)?; file.write(ser.as_bytes())?; Ok(()) } /* pub fn from_path(path: &Path) -> Result { match (path.is_file(), path.is_dir()) { (false, false) => Err(ReadFileError::FileNotFound), (false, true) => Err(ReadFileError::NotAFile), (true, _) => Ok(()), }?; let metadata = path.metadata().map_err(ReadFileError::IOError)?; let id = path .file_name() .map(|s| String::from(s.to_string_lossy())) .ok_or(ReadFileError::NotAFile)?; let created = metadata .created() .map(|m| DateTime::from(m)) .map_err(|err| ReadFileError::IOError(err))?; let file_type = String::from( mime_guess::from_path(path) .first_or_octet_stream() .essence_str(), ); let hash = FileInfo::hash_file(path)?; Ok(FileInfo { id, size: metadata.len(), created, file_type, hash: hash.as_string(), root: PathBuf::from(path.parent().unwrap()), }) } */ /* fn hash_file(path: &Path) -> Result { let mut buf = Vec::new(); let mut file = std::fs::File::open(path).map_err(ReadFileError::from)?; file.read_to_end(&mut buf).map_err(ReadFileError::from)?; let mut vec = Vec::new(); vec.extend_from_slice(Sha256::digest(&buf).as_slice()); Ok(HexString::from_bytes(&vec)) } */ /* fn metadata_path(id: &str, root: &Path) -> PathBuf { let mut path = PathBuf::from(root); path.push(".metadata"); path.push(id.clone()); append_extension(&path, "json") } pub fn delete(&self) -> Result<(), FileError> { let path = FileInfo::metadata_path(&self.id, &self.root); remove_file(path).map_err(FileError::from) } */ } #[cfg(test)] mod test { use super::*; use crate::store::utils::FileCleanup; use crate::store::PathResolver; #[test] fn it_saves_and_loads_metadata() { let resolver = PathResolver::from("fixtures/1617654d-a588-4714-b4fa-e00ed0a8a607"); let _cleanup = FileCleanup(resolver.metadata_path()); let created = Utc::now(); let info = FileInfo { size: 23777, created, file_type: "image/png".to_owned(), hash: "abcdefg".to_owned(), }; info.save(resolver.metadata_path()).unwrap(); let info_ = FileInfo::load(resolver.metadata_path()).unwrap(); assert_eq!(info_.size, 23777); assert_eq!(info_.created, info.created); assert_eq!(info_.file_type, "image/png"); assert_eq!(info_.hash, info.hash); } }