From f1d877c38fb70967c73fa20bfda8518110e30a99 Mon Sep 17 00:00:00 2001 From: Mohammad Julfikar Date: Mon, 28 Aug 2023 21:45:27 +0800 Subject: [PATCH] - release 0.1.67 - result set extension --- Cargo.toml | 3 +- src/extension/flinch_ext.rs | 133 +++++++++++++++++++++++++++++++++++ src/extension/func_result.rs | 14 ++++ src/extension/mod.rs | 42 +++++++++++ src/extension/value.rs | 62 ++++++++++++++++ src/lib.rs | 1 + 6 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 src/extension/flinch_ext.rs create mode 100644 src/extension/func_result.rs create mode 100644 src/extension/mod.rs create mode 100644 src/extension/value.rs diff --git a/Cargo.toml b/Cargo.toml index 592541f..a542c31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flinch" -version = "0.1.66" +version = "0.1.67" edition = "2021" authors = ["Mohammad Julfikar ", "Mohammad Julfikar "] categories = ["parser-implementations","caching","database-implementations"] @@ -16,6 +16,7 @@ repository = "https://github.com/mjm918/flinch" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.73" anyhow = "1.0.70" bincode = "2.0.0-rc.3" chrono = "0.4.24" diff --git a/src/extension/flinch_ext.rs b/src/extension/flinch_ext.rs new file mode 100644 index 0000000..1d14fcf --- /dev/null +++ b/src/extension/flinch_ext.rs @@ -0,0 +1,133 @@ +use std::sync::Arc; +use async_trait::async_trait; +use log::{error, trace}; +use rayon::prelude::*; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; +use crate::database::Database; +use crate::doc::QueryBased; +use crate::doc_trait::Document; +use crate::extension::FlinchDbHelper; + +#[async_trait] +impl FlinchDbHelper for Arc> { + async fn push<'a, T>(&self, col: &'a str, value: T) where T: Serialize + Deserialize<'a> + Sync + Send + ToString { + if let Ok(col) = self.using(col) { + let document = QueryBased::from_str(value.to_string().as_str()).unwrap(); + let _ = col.put(col.id(), document).await; + } else { + error!("no collection `{}` found in flinch",col); + } + } + + async fn save<'a, T>(&self, col: &'a str, key: &'a str, value: T) where T: Serialize + Deserialize<'a> + Sync + Send + ToString { + if let Ok(col) = self.using(col) { + let document = QueryBased::from_str(value.to_string().as_str()).unwrap(); + let _ = col.put(format!("{}", key), document).await; + } else { + error!("no collection `{}` found in flinch",col); + } + } + + async fn save_with_ttl<'a, T>(&self, col: &'a str, key: &'a str, value: T, ttl: i64) where T: Serialize + Deserialize<'a> + Sync + Send + ToString { + if let Ok(col) = self.using(col) { + let document = QueryBased::from_str(value.to_string().as_str()).unwrap(); + let _ = col.put(format!("{}", key), document).await; + let _ = col.put_ttl(format!("{}", key), ttl).await; + } else { + error!("no collection `{}` found in flinch",col); + } + } + + fn get_object(&self, col: &str, key: &str) -> Map { + if let Ok(col) = self.using(col) { + let qb = col.get(&format!("{}", key)); + return qb.get_object(); + } else { + error!("no collection `{}` found in flinch",col); + } + Map::new() + } + + fn find_all(&self, col: &str) -> Option> where T: From> { + match self.using(col) { + Ok(col) => { + let all = crossbeam_queue::SegQueue::new(); + col.iter().for_each(|kv|{ + let v = kv.value(); + trace!("{:?}",v.object()); + all.push(v.object().clone()); + }); + let res = all.into_iter().map(|item|T::from(item)).collect::>(); + Some(res) + }, + Err(err) => { + error!("{:?}",err); + None + }, + } + } + + fn find_one(&self, col: &str, index: &str) -> Option where T: From> { + match self.using(col) { + Ok(col) => { + let res = col.get_index(index); + if res.data.is_some() { + return Some(T::from(res.get_object())); + } + None + } + Err(err) => { + error!("{:?}",err); + None + }, + } + } + + fn find_id_by_index(&self, col: &str, index: &str) -> Option { + match self.using(col) { + Ok(col) => { + let res = col.get_index(index); + if res.data.is_some() { + let id = res.data.unwrap(); + return Some(id.0); + } + None + } + Err(err) => { + error!("{:?}",err); + None + } + } + } + + async fn delete_id(&self, col: &str, id: &str) -> bool { + match self.using(col) { + Ok(col) => { + col.delete(format!("{}",id)).await; + true + } + Err(_) => false + } + } + + async fn update_by_index<'a, T>(&self, col: &'a str, index: &'a str, value: T) -> bool where T: Serialize + Deserialize<'a> + Sync + Send + ToString { + if let Ok(db) = self.using(col) { + return match self.find_id_by_index(col,index) { + None => false, + Some(id) => { + let key = format!("{}",id); + let document = QueryBased::from_str(value.to_string().as_str()).unwrap(); + match db.put(key.to_owned(), document).await { + Ok(_) => true, + Err(err) => { + error!("{}",err); + false + } + } + } + }; + } + false + } +} \ No newline at end of file diff --git a/src/extension/func_result.rs b/src/extension/func_result.rs new file mode 100644 index 0000000..8f0f22a --- /dev/null +++ b/src/extension/func_result.rs @@ -0,0 +1,14 @@ +use serde_json::{Map, Value}; +use crate::doc::QueryBased; +use crate::doc_trait::Document; +use crate::extension::FuncResultExtractor; +use crate::headers::FuncResult; + +impl FuncResultExtractor for FuncResult> { + fn get_object(&self) -> Map { + if let Some((_key, qb)) = &self.data { + return qb.object().clone(); + } + Map::new() + } +} \ No newline at end of file diff --git a/src/extension/mod.rs b/src/extension/mod.rs new file mode 100644 index 0000000..54a7705 --- /dev/null +++ b/src/extension/mod.rs @@ -0,0 +1,42 @@ +pub mod flinch_ext; +mod func_result; +pub mod value; + +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use serde::de::DeserializeOwned; +use serde_json::{Map, Value}; + +pub trait JsonExt { + fn to_object(&self) -> Map; + fn to_array(&self) -> Vec; + fn any_to_str(&self) -> String; + fn to_struct<'a, T>(&self) -> serde_json::Result where T : Serialize + DeserializeOwned; +} + +pub trait JsonMapExt { + fn get_str(&self, name: &str) -> String; + fn get_object(&self, name: &str) -> Map; + fn get_array(&self, name: &str) -> Vec; +} + +pub trait FuncResultExtractor { + fn get_object(&self) -> Map; +} + +#[async_trait] +pub trait FlinchDbHelper { + async fn push<'a, T>(&self, col: &'a str, value: T) where T: Serialize + Deserialize<'a> + Sync + Send + ToString; + async fn save<'a, T>(&self, col: &'a str, key: &'a str, value: T) where T: Serialize + Deserialize<'a> + Sync + Send + ToString; + async fn save_with_ttl<'a, T>(&self, col: &'a str, key: &'a str, value: T, ttl: i64) where T: Serialize + Deserialize<'a> + Sync + Send + ToString; + fn get_object(&self, col: &str, key: &str) -> Map; + fn find_all(&self, col: &str) -> Option> where T: From> ; + fn find_one(&self, col: &str, index: &str) -> Option where T: From> ; + fn find_id_by_index(&self, col: &str, index: &str) -> Option; + async fn delete_id(&self, col: &str, id: &str) -> bool; + async fn update_by_index<'a, T>(&self, col: &'a str, index: &'a str, value: T) -> bool where T: Serialize + Deserialize<'a> + Sync + Send + ToString; +} + +pub trait ResultSet { + fn result_array(self) -> Vec; +} diff --git a/src/extension/value.rs b/src/extension/value.rs new file mode 100644 index 0000000..5b3dfa8 --- /dev/null +++ b/src/extension/value.rs @@ -0,0 +1,62 @@ +use serde::Serialize; +use serde::de::DeserializeOwned; +use serde_json::{Map, Value}; +use crate::extension::{JsonExt, JsonMapExt}; + +impl JsonExt for Value { + fn to_object(&self) -> Map { + let tmp_map = Map::new(); + let map = self.as_object().unwrap_or(&tmp_map).clone(); + map + } + + fn to_array(&self) -> Vec { + let arr = self.as_array().unwrap_or(&vec![]).clone(); + arr + } + + fn any_to_str(&self) -> String { + match self.as_bool() { + None => match self.is_string() { + true => { + let str = self.as_str().unwrap_or("").to_owned(); + str + } + false => self.to_string() + } + Some(in_bool) => match in_bool { + true => format!("true"), + false => format!("false") + } + } + } + + fn to_struct<'a, T>(&self) -> serde_json::Result where T : Serialize + DeserializeOwned { + let res: serde_json::Result = serde_json::from_value(self.clone()); + res + } +} + +impl JsonMapExt for Map { + fn get_str(&self, name: &str) -> String { + let tmp = Value::String("".to_string()); + let df = self.get(name).unwrap_or(&tmp); + let string = df.as_str().unwrap_or(""); + string.to_string() + } + + fn get_object(&self, name: &str) -> Map { + let tmp_map = Map::new(); + let tmp = Value::Object(tmp_map.to_owned()); + let df = self.get(name).unwrap_or(&tmp); + let obj = df.as_object().unwrap_or(&tmp_map).clone(); + obj + } + + fn get_array(&self, name: &str) -> Vec { + let tmp = Value::Array(vec![]); + let df = self.get(name).unwrap_or(&tmp); + let arr = df.as_array().unwrap_or(&vec![]).clone(); + arr + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index cbf3bbe..d4fd425 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,3 +21,4 @@ pub mod headers; pub mod query; pub mod schemas; pub mod errors; +pub mod extension;