Last active
April 13, 2020 22:17
-
-
Save fxdave/4b4e363322e6141add00b6bb09d8eb04 to your computer and use it in GitHub Desktop.
Bulky Cached Rust File Repository
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| mod seri { | |
| pub trait Deserialize { | |
| fn deserialize(atoms: Vec<String>) -> Option<Self> | |
| where | |
| Self: Sized; | |
| } | |
| } | |
| mod db { | |
| use super::seri::Deserialize; | |
| use std::error::Error; | |
| use std::fs::File; | |
| use std::io::{BufRead, BufReader}; | |
| use std::path::{Path, PathBuf}; | |
| pub trait GenericDB { | |
| fn find_one<D: Deserialize>( | |
| &self, | |
| query: impl Fn(D) -> Option<D>, | |
| ) -> Result<Option<D>, Box<dyn Error>>; | |
| } | |
| pub struct DB { | |
| path: PathBuf, | |
| } | |
| impl DB { | |
| pub fn new(path: &Path) -> DB { | |
| DB { | |
| path: path.to_owned(), | |
| } | |
| } | |
| } | |
| impl GenericDB for DB { | |
| fn find_one<D: Deserialize>( | |
| &self, | |
| query: impl Fn(D) -> Option<D>, | |
| ) -> Result<Option<D>, Box<dyn Error>> { | |
| let mut lines = BufReader::new(File::open(&self.path)?).lines(); | |
| let result: Option<D> = lines.find_map(|raw_user_res| { | |
| raw_user_res | |
| .ok() | |
| .and_then(|raw_user| { | |
| Some(raw_user.split(";").map(|atom| atom.to_owned()).collect()) | |
| }) | |
| .and_then(|atoms| D::deserialize(atoms)) | |
| .and_then(&query) | |
| }); | |
| Ok(result) | |
| } | |
| } | |
| } | |
| mod model { | |
| use std::error::Error; | |
| pub trait ModelInterface: Clone {} | |
| pub trait RepositoryInterface<M: ModelInterface> { | |
| fn find_by_name(&mut self, name: &'static str) -> Result<Option<M>, Box<dyn Error>>; | |
| } | |
| } | |
| mod cache { | |
| pub trait Cache<T> { | |
| fn get(&self, key: &'static str) -> Option<T>; | |
| fn set(&mut self, key: &'static str, val: &T); | |
| } | |
| } | |
| mod model_cache { | |
| use super::cache::Cache; | |
| use super::model::{ModelInterface, RepositoryInterface}; | |
| use std::error::Error; | |
| use std::collections::HashMap; | |
| pub struct ModelCacher<M> { | |
| storage: HashMap<&'static str, M>, | |
| } | |
| impl<M: ModelInterface> ModelCacher<M> { | |
| pub fn new() -> ModelCacher<M> { | |
| ModelCacher { | |
| storage: HashMap::new(), | |
| } | |
| } | |
| } | |
| impl<M: ModelInterface> Cache<M> for ModelCacher<M> { | |
| fn get(&self, key: &'static str) -> Option<M> { | |
| match self.storage.get(key) { | |
| Some(el) => { | |
| println!("Loaded from cache."); | |
| Some(el.clone()) | |
| } | |
| None => { | |
| println!("Cache key missmatch."); | |
| None | |
| } | |
| } | |
| } | |
| fn set(&mut self, key: &'static str, val: &M) { | |
| self.storage.insert(key, val.clone()); | |
| } | |
| } | |
| pub struct CachedRepository<M: ModelInterface, R: RepositoryInterface<M>> { | |
| pub repo: R, | |
| pub cache: ModelCacher<M>, | |
| } | |
| impl<M: ModelInterface, R: RepositoryInterface<M>> CachedRepository<M, R> { | |
| pub fn new(repo: R, cache: ModelCacher<M>) -> CachedRepository<M, R> { | |
| CachedRepository { repo, cache } | |
| } | |
| } | |
| impl<M: ModelInterface, R: RepositoryInterface<M>> RepositoryInterface<M> | |
| for CachedRepository<M, R> | |
| { | |
| fn find_by_name(&mut self, name: &'static str) -> Result<Option<M>, Box<dyn Error>> { | |
| let cached = self.cache.get(name); | |
| match cached { | |
| Some(val) => Ok(Some(val)), | |
| None => { | |
| let find = self.repo.find_by_name(name); | |
| match find { | |
| Ok(Some(val)) => { | |
| self.cache.set(name, &val); | |
| Ok(Some(val)) | |
| } | |
| _ => find, | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| mod user { | |
| use super::model::{ModelInterface, RepositoryInterface}; | |
| use super::seri::Deserialize; | |
| #[derive(Debug, Clone)] | |
| pub struct Model { | |
| pub id: i32, | |
| pub name: String, | |
| pub email: String, | |
| } | |
| impl ModelInterface for Model {} | |
| impl Deserialize for Model { | |
| fn deserialize(atoms: Vec<String>) -> Option<Self> { | |
| Some(Self { | |
| id: atoms.get(0)?.parse().ok()?, | |
| email: atoms.get(1)?.to_owned(), | |
| name: atoms.get(2)?.to_owned(), | |
| }) | |
| } | |
| } | |
| use super::db::{GenericDB, DB}; | |
| use std::error::Error; | |
| use std::path::Path; | |
| pub struct Repository {} | |
| impl Repository { | |
| pub fn new() -> Repository { | |
| Repository {} | |
| } | |
| } | |
| impl RepositoryInterface<Model> for Repository { | |
| fn find_by_name(&mut self, name: &'static str) -> Result<Option<Model>, Box<dyn Error>> { | |
| let userdb = DB::new(Path::new("./users.txt")); | |
| userdb.find_one( | |
| |user: Model| { | |
| if user.name == name { | |
| Some(user) | |
| } else { | |
| None | |
| } | |
| }, | |
| ) | |
| } | |
| } | |
| } | |
| use model::RepositoryInterface; | |
| use std::error::Error; | |
| fn main() -> Result<(), Box<dyn Error>> { | |
| let mut cached_user_repository = model_cache::CachedRepository::new( | |
| user::Repository::new(), | |
| model_cache::ModelCacher::new(), | |
| ); | |
| match cached_user_repository.find_by_name("Nice")? { | |
| Some(u) => println!("{:?}", u), // Cache key missmatch. Model { id: 3, name: "Nice", email: "lol@lol.hu" } | |
| None => println!("User not found"), | |
| } | |
| match cached_user_repository.find_by_name("Asd")? { | |
| Some(u) => println!("{:?}", u), // Cache key missmatch. Model { id: 1, name: "Asd", email: "lol@lol.hu" } | |
| None => println!("User not found"), | |
| } | |
| match cached_user_repository.find_by_name("Nice")? { | |
| Some(u) => println!("{:?}", u), // Loaded from cache. Model { id: 3, name: "Nice", email: "lol@lol.hu" } | |
| None => println!("User not found"), | |
| } | |
| Ok(()) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 1;lol@lol.hu;Asd | |
| 2;lol@lol.hu;Lol | |
| 3;lol@lol.hu;Nice |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment