SQLite-backed Key / Value Store
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: async trait for dynamic dispatch on store

+32 -25
+12
Cargo.lock
··· 92 92 checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 93 93 94 94 [[package]] 95 + name = "async-trait" 96 + version = "0.1.80" 97 + source = "registry+https://github.com/rust-lang/crates.io-index" 98 + checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" 99 + dependencies = [ 100 + "proc-macro2", 101 + "quote", 102 + "syn 2.0.66", 103 + ] 104 + 105 + [[package]] 95 106 name = "atoi" 96 107 version = "2.0.0" 97 108 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1046 1057 version = "0.9.0" 1047 1058 dependencies = [ 1048 1059 "anyhow", 1060 + "async-trait", 1049 1061 "clap", 1050 1062 "dirs", 1051 1063 "serde",
+1
Cargo.toml
··· 19 19 serde = { version = "1.0.203", features = ["derive"] } 20 20 tokio = { version = "1.38.0", features = ["full"] } 21 21 sqlx = { version = "0.7.4", features = ["runtime-tokio", "sqlite"] } 22 + async-trait = "0.1.80" 22 23 23 24 # The profile that 'cargo dist' will build with 24 25 [profile.dist]
+9 -21
src/main.rs
··· 3 3 mod utils; 4 4 5 5 use cli::*; 6 - use store::SafirStore; 7 6 8 7 use anyhow::{Context, Result}; 9 8 ··· 12 11 let cli = Cli::parse(); 13 12 let mut safir = store::init_safir().await.context("loading safir store")?; 14 13 14 + // This is stupid 15 15 match cli.command { 16 - Commands::Add { key, value } => { 17 - safir.add(key.to_owned(), value.to_owned()).await?; 18 - } 19 - Commands::Get { keys } => { 20 - safir.get(keys.to_owned()).await?; 21 - } 22 - Commands::Rm { keys } => { 23 - safir.remove(keys.to_owned()).await?; 24 - } 25 - Commands::Alias { keys } => { 16 + Commands::Add { key, value } => safir.add(key.to_owned(), value.to_owned()).await?, 17 + Commands::Get { keys } => safir.get(keys.to_owned()).await?, 18 + Commands::Rm { keys } => safir.remove(keys.to_owned()).await?, 19 + Commands::Alias { keys: _ } => { 26 20 // TODO: Fix custom displays 27 21 unimplemented!("alias needs work"); 28 22 // safir.custom_display("alias", keys.to_owned()).await?; 29 23 } 30 - Commands::Export { keys } => { 24 + Commands::Export { keys: _ } => { 31 25 unimplemented!("export needs work"); 32 26 // safir.custom_display("export", keys.to_owned()).await?; 33 27 } 34 - Commands::List => { 35 - safir.list().await?; 36 - } 37 - Commands::Clear => { 38 - safir.clear().await?; 39 - } 40 - Commands::Purge => { 41 - safir.purge().await?; 42 - } 28 + Commands::List => safir.list().await?, 29 + Commands::Clear => safir.clear().await?, 30 + Commands::Purge => safir.purge().await?, 43 31 Commands::Mode { mode } => { 44 32 println!("Mode: {mode:?}"); 45 33 }
+2
src/store/db_store.rs
··· 1 1 use anyhow::{Context, Result}; 2 + use async_trait::async_trait; 2 3 use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool, SqlitePoolOptions}; 3 4 4 5 use std::path::PathBuf; ··· 41 42 } 42 43 } 43 44 45 + #[async_trait] 44 46 impl SafirStore for SqliteStore { 45 47 async fn add(&mut self, key: String, value: String) -> Result<()> { 46 48 Ok(())
+3
src/store/file_store.rs
··· 1 1 use crate::{store::SafirStore, utils}; 2 2 use anyhow::Result; 3 + use async_trait::async_trait; 3 4 use std::{collections::HashMap, path::PathBuf}; 4 5 6 + #[derive(Debug, Clone)] 5 7 pub struct KVStore { 6 8 pub path: PathBuf, 7 9 pub store: HashMap<String, String>, ··· 33 35 } 34 36 } 35 37 38 + #[async_trait] 36 39 impl SafirStore for KVStore { 37 40 async fn add(&mut self, key: String, value: String) -> Result<()> { 38 41 if let Some(v) = self.store.get(&key) {
+5 -4
src/store/mod.rs
··· 6 6 use std::path::Path; 7 7 8 8 use anyhow::{Context, Result}; 9 + use async_trait::async_trait; 9 10 use clap::ValueEnum; 10 11 use db_store::SqliteStore; 11 12 use file_store::KVStore; 12 13 use serde::{Deserialize, Serialize}; 13 14 15 + #[async_trait] 14 16 pub trait SafirStore { 15 17 async fn add(&mut self, key: String, value: String) -> Result<()>; 16 18 async fn get(&self, keys: Vec<String>) -> Result<()>; ··· 44 46 } 45 47 } 46 48 47 - pub async fn init_safir() -> Result<impl SafirStore> { 49 + pub async fn init_safir() -> Result<Box<dyn SafirStore>> { 48 50 let ws = utils::create_safir_workspace(); 49 51 let cfg = SafirConfig::load(&ws).expect("can't load safir config"); 50 - 51 52 match cfg.mode { 52 - SafirMode::File => Ok(KVStore::load(ws)), 53 - SafirMode::Database => unimplemented!("fix this"), 53 + SafirMode::File => Ok(Box::new(KVStore::load(ws))), 54 + SafirMode::Database => Ok(Box::new(SqliteStore::load(ws).await?)), 54 55 } 55 56 }