use std::{ cell::{RefCell, RefMut}, collections::{HashMap, hash_map::Entry}, }; use crate::{ Error, Result, file::{self, FileTrait}, sharry::{AliasID, Client, FileID, ShareID, Uri, json}, }; use super::mock_ids::CheckID; #[derive(Debug)] pub struct MockClient { shares: RefCell>, } #[derive(Debug, Default)] struct MockShare { files: HashMap, } #[derive(Debug)] struct MockFile { name: String, size: u64, offset: u64, } impl MockClient { fn insert_share(&self, share_id: &ShareID) -> Result<()> { let mut shares = self.shares.borrow_mut(); let Entry::Vacant(entry) = shares.entry(share_id.to_string()) else { return Err(Error::response(format_args!( "Can't create share {share_id:?}!" ))); }; entry.insert(MockShare::default()); Ok(()) } fn insert_file( &self, share_id: &ShareID, file_id: &FileID, name: String, size: u64, ) -> Result<()> { let mut share = self.get_share_mut(share_id)?; let Entry::Vacant(entry) = share.files.entry(file_id.to_string()) else { return Err(Error::response(format_args!( "Can't create file {file_id:?}!" ))); }; entry.insert(MockFile { name, size, offset: 0, }); Ok(()) } fn get_share_mut<'t>(&'t self, share_id: &ShareID) -> Result> { let share_id = &share_id.to_string(); let shares = self.shares.borrow_mut(); shares .get(share_id) .ok_or_else(|| Error::response(format_args!("Can't find share {share_id:?}!")))?; // share exists Ok(RefMut::map(shares, |shares| { shares.get_mut(share_id).expect("checked but None!") })) } fn get_file_mut<'t>( &'t self, share_id: &ShareID, file_id: &FileID, ) -> Result> { let file_id = &file_id.to_string(); let share = self.get_share_mut(share_id)?; share .files .get(file_id) .ok_or_else(|| Error::response(format_args!("Can't find file {file_id:?}!")))?; // file exists Ok(RefMut::map(share, move |share| { share.files.get_mut(file_id).expect("checked but None!") })) } } impl Client for MockClient { fn share_create( &self, uri: &Uri, alias_id: &AliasID, _: json::NewShareRequest, ) -> Result { (uri, alias_id).check()?; let share_id = true.into(); self.insert_share(&share_id)?; Ok(share_id) } fn share_notify(&self, uri: &Uri, alias_id: &AliasID, share_id: &ShareID) -> crate::Result<()> { (uri, alias_id).check()?; share_id.check()?; Ok(()) } fn file_create( &self, uri: &Uri, alias_id: &AliasID, share_id: &ShareID, file: &file::Checked, ) -> Result { (uri, alias_id).check()?; share_id.check()?; let file_id = true.into(); self.insert_file( share_id, &file_id, file.get_name().to_string(), file.get_size(), )?; Ok(file_id) } fn file_patch( &self, uri: &Uri, alias_id: &AliasID, share_id: &ShareID, chunk: &file::Chunk, ) -> Result<()> { (uri, alias_id).check()?; (share_id, chunk.get_file_id()).check()?; // TODO: `chunk` must align to a full MiB let file = self.get_file_mut(share_id, chunk.get_file_id())?; todo!() // Ok(()) } }