use crate::model::*; use crate::persistency::*; use crate::protocol::*; use crate::search::*; use std::path::Path; use std::sync::*; #[derive(Clone)] pub struct ServerState { data_store: Arc>, } impl ServerState { #[allow(dead_code)] pub fn new(storage_path: &Path) -> std::io::Result { Ok(Self { data_store: Arc::new(RwLock::new(DataStore::new(&storage_path)?)), }) } } impl ProtocolHandler for ServerState { fn query(&mut self, query: &[String]) -> ProtocolResult> { let q = Query::parse(query) .map_err(|e| ProtocolError::BadRequest(format!("Invalid Query String: {:?}", e)))?; let data_store = self.data_store.read().unwrap(); let mut textures = data_store.borrow_textures(); Ok(q.search(&mut textures)) } fn get_texture_by_id(&mut self, id: &str) -> ProtocolResult> { let data_store = self.data_store.read().unwrap(); Ok(data_store.texture_by_id(id)) } fn get_texture_by_name(&mut self, name: &str) -> ProtocolResult> { let data_store = self.data_store.read().unwrap(); Ok(data_store.texture_by_name(name)) } fn get_texture_file(&mut self, hash: Sha256) -> ProtocolResult> { let data_store = self.data_store.read().unwrap(); let data = data_store.read_texture_file_by_hash(&hash)?; Ok(data) } fn get_texture_preview( &mut self, hash: Sha256, format: TextureFormat, ) -> ProtocolResult> { let mut data_store = self.data_store.write().unwrap(); match data_store.get_texture_preview(&hash, format) { Ok(data) => Ok(data), Err(TextureFileError::NotFound) => Err(ProtocolError::FileNotFound( "Texture not found!".to_string(), )), Err(TextureFileError::ImageError(_)) => Err(ProtocolError::FileNotFound( "Didn't Find valid Texture File".to_string(), )), Err(TextureFileError::IoError(err)) => Err(ProtocolError::InternalServerError(err)), } } fn replace_texture( &mut self, delete: Option, insert: Option, insert_texture_data: Option>, ) -> ProtocolResult { let mut data_store = self.data_store.write().unwrap(); match insert_texture_data { Some(data) => { data_store.store_texture_file(&data)?; } None => (), } match (delete, insert) { (Some(delete), Some(insert)) => { if !data_store.is_texture_file_on_disk(&insert.texture_hash) { return Ok(ReplaceTextureStatus::NeedTextureData(insert.texture_hash)); } if !data_store.delete(&delete) { return Err(ProtocolError::Conflict( "Delete Texture was modified!".to_string(), )); } if !data_store.insert(insert) { // undo delete // panics if texture file is delete during delete and reinsert. // unlikely to happen. assert!(data_store.insert(delete)); return Err(ProtocolError::Conflict( "Name or Id already taken.".to_string(), )); } data_store.flush_metadata()?; Ok(ReplaceTextureStatus::Ok) } (Some(delete), None) => { if !data_store.delete(&delete) { return Err(ProtocolError::Conflict( "Delete Texture was modified!".to_string(), )); } data_store.flush_metadata()?; Ok(ReplaceTextureStatus::Ok) } (None, Some(insert)) => { if !data_store.is_texture_file_on_disk(&insert.texture_hash) { return Ok(ReplaceTextureStatus::NeedTextureData(insert.texture_hash)); } if !data_store.insert(insert) { // undo delete return Err(ProtocolError::Conflict( "Name or Id already taken.".to_string(), )); } data_store.flush_metadata()?; Ok(ReplaceTextureStatus::Ok) } (None, None) => Ok(ReplaceTextureStatus::Ok), } } }