use once_cell::sync::Lazy; use std::collections::HashSet; use std::io::Read; use std::iter::Iterator; use std::time::{Duration, SystemTime}; use u_lib::utils::SharedStorage; use uuid::Uuid; type Data = Box; /// This struct holds uids of various readable objects (files, streams, etc...) /// with timeout and permissions for any uids to read data struct MappedData { //ids that allowed to read the data for_ids: HashSet, created: SystemTime, timeout: Duration, data: Data, } impl MappedData { pub fn new( ids: impl Iterator, data: impl Read + Send + Sync + 'static, timeout: Duration, ) -> Self { MappedData { for_ids: ids.collect(), created: SystemTime::now(), timeout, data: Box::new(data), } } } static MAPPER: Lazy> = SharedStorage::new(); pub struct Mapper; impl Mapper { fn remove_overdue() { MAPPER .lock() .retain(|_, v| v.created.elapsed().unwrap() < v.timeout); } pub fn get(item_uid: Uuid, getter_uid: Uuid) -> Option { Self::remove_overdue(); let allowed_ids = MAPPER.lock().get(&item_uid)?.for_ids; if allowed_ids.contains(&getter_uid) { MAPPER.lock().remove(&item_uid).map(|d| d.data) } else { None } } pub fn set( for_ids: impl Iterator, data: impl Read + Send + Sync + 'static, timeout: Option, ) -> Uuid { Self::remove_overdue(); let uid = Uuid::new_v4(); let timeout = timeout.unwrap_or(Duration::from_secs(60)); let mapped = MappedData::new(for_ids, data, timeout); MAPPER.lock().insert(uid, mapped); uid } } // init: // fill index struct with files allowed to download (probably auto-refresh index on file adding) // hashmap // download: // 1) agent sends download_request with hash of wanted file // 2) handler checks if this agent is allowed to dl file // 3) if all ok, create in entry in mapper and return its uid and hashsum to agent // 4) agent downloads file by uid, uid destructed after that