From 6b2b8db4c4dfa25188d1589f56c46d7860afc853 Mon Sep 17 00:00:00 2001 From: 4t145 Date: Tue, 17 Oct 2023 18:02:15 +0800 Subject: [PATCH] add tardis_static macro --- tardis/src/basic/field.rs | 25 +++++---- tardis/src/utils.rs | 3 +- tardis/src/utils/tardis_static.rs | 84 +++++++++++++++++++++++++++++ tardis/src/web/web_resp.rs | 4 +- tardis/src/web/web_server/module.rs | 8 +++ 5 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 tardis/src/utils/tardis_static.rs diff --git a/tardis/src/basic/field.rs b/tardis/src/basic/field.rs index b595e01d..1e5b8706 100644 --- a/tardis/src/basic/field.rs +++ b/tardis/src/basic/field.rs @@ -2,14 +2,17 @@ use std::ops::Deref; use regex::Regex; -use crate::utils::mapper::{Base64Decode, Base64Encode, Mapped, Trim}; - -lazy_static! { - static ref R_PHONE: Regex = Regex::new(r"^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$").expect("Regular parsing error"); - static ref R_MAIL: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") +use crate::{ + tardis_static, + utils::mapper::{Base64Decode, Base64Encode, Mapped, Trim}, +}; + +tardis_static! { + pub r_phone: Regex = Regex::new(r"^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$").expect("Regular parsing error"); + pub r_mail: Regex = Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") .expect("Regular parsing error"); - static ref R_CODE_NCS: Regex = Regex::new(r"^[a-z0-9_]+$").expect("Regular parsing error"); - static ref R_CODE_CS: Regex = Regex::new(r"^[A-Za-z0-9_]+$").expect("Regular parsing error"); + pub r_code_ncs: Regex = Regex::new(r"^[a-z0-9_]+$").expect("Regular parsing error"); + pub r_code_cs: Regex = Regex::new(r"^[A-Za-z0-9_]+$").expect("Regular parsing error"); } static BASE62: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -42,24 +45,24 @@ pub struct TardisField; impl TardisField { /// Determine if it is a cell phone number (only supports mainland China) / 判断是否是手机号(仅支持中国大陆) pub fn is_phone(&self, phone: &str) -> bool { - R_PHONE.is_match(phone) + r_phone().is_match(phone) } /// Determine if it is a email / 判断是否是邮箱 pub fn is_mail(&self, mail: &str) -> bool { - R_MAIL.is_match(mail) + r_mail().is_match(mail) } /// Determine if it contains only numbers, lowercase letters and underscores / /// 判断是否只包含数字、小写字母及下划线 pub fn is_code_cs(&self, str: &str) -> bool { - R_CODE_CS.is_match(str) + r_code_cs().is_match(str) } /// Determine if only numbers, upper and lower case letters and underscores are included / /// 判断是否只包含数字、大小写字母及下划线 pub fn is_code_ncs(&self, str: &str) -> bool { - R_CODE_NCS.is_match(str) + r_code_ncs().is_match(str) } /// Generate NanoId / 生成NanoId diff --git a/tardis/src/utils.rs b/tardis/src/utils.rs index 97dcc738..468e3660 100644 --- a/tardis/src/utils.rs +++ b/tardis/src/utils.rs @@ -2,7 +2,6 @@ pub mod cached_json_value; pub(crate) use cached_json_value::*; pub mod tardis_component; pub(crate) use tardis_component::*; -// pub mod hot; pub mod initializer; - pub mod mapper; +pub mod tardis_static; diff --git a/tardis/src/utils/tardis_static.rs b/tardis/src/utils/tardis_static.rs new file mode 100644 index 00000000..7671f1af --- /dev/null +++ b/tardis/src/utils/tardis_static.rs @@ -0,0 +1,84 @@ +/// A macro to create a static variable that is lazily initialized, using [`std::sync::OnceLock`] or [`tokio::sync::OnceCell`] to store. +/// # Examples +/// ```ignore +/// tardis_static! { +/// pub config: Config = Config::new(); +/// } +/// +/// // then use it as a function, it will return a static reference. +/// let config = config(); +/// ``` +/// +/// if you want to initialize the static variable asynchronously, you can use `async` keyword. +/// ```ignore +/// tardis_static! { +/// pub async x: Config = async { +/// wait_other_async().await; +/// retrive_config().await +/// }; +/// } +/// ``` +/// for those type that implement [`Default`] trait, you emit the initial value. +/// ```ignore +/// tardis_static! { +/// pub config: Config; +/// } +/// +/// ``` + +#[macro_export] +macro_rules! tardis_static { + () => { + }; + ($(#[$attr:meta])* $vis:vis async $ident:ident :$Type:ty = $init: expr; $($rest: tt)*) => { + $(#[$attr])* + $vis async fn $ident() -> &'static $Type { + use tokio::sync::OnceCell; + static STATIC_VAL: OnceCell<$Type> = OnceCell::const_new(); + + STATIC_VAL.get_or_init(|| $init).await + } + $crate::tardis_static!($($rest)*); + }; + + ($(#[$attr:meta])* $vis:vis $ident:ident :$Type:ty = $init: expr; $($rest: tt)*) => { + $(#[$attr])* + $vis fn $ident() -> &'static $Type { + use std::sync::OnceLock; + static STATIC_VAL: OnceLock<$Type> = OnceLock::new(); + + STATIC_VAL.get_or_init(|| $init) + } + $crate::tardis_static!($($rest)*); + }; + + ($(#[$attr:meta])* $vis:vis $ident:ident :$Type:ty; $($rest: tt)*) => { + $crate::tardis_static!($(#[$attr])* $vis $ident: $Type = Default::default(); $($rest)*); + }; +} + +#[cfg(test)] +#[test] +#[allow(dead_code)] +fn test_tardis_static_macro() { + #[derive(Default, Clone)] + struct Config {} + + tardis_static! { + config: Config = Config::default(); + } + async fn wait_other_async() {} + async fn retrive_config() -> Config { + config().clone() + } + tardis_static! { + async async_config: Config = async { + wait_other_async().await; + retrive_config().await + }; + } + + tardis_static! { + config_defualt: Config; + } +} diff --git a/tardis/src/web/web_resp.rs b/tardis/src/web/web_resp.rs index 2bb5e8a1..484baf49 100644 --- a/tardis/src/web/web_resp.rs +++ b/tardis/src/web/web_resp.rs @@ -131,5 +131,5 @@ where pub records: Vec, } -#[derive(Object, Deserialize, Serialize, Clone, Debug)] -pub struct Void {} +#[derive(Object, Deserialize, Serialize, Clone, Debug, Default, Copy)] +pub struct Void; diff --git a/tardis/src/web/web_server/module.rs b/tardis/src/web/web_server/module.rs index 5475b0ea..8a276621 100644 --- a/tardis/src/web/web_server/module.rs +++ b/tardis/src/web/web_server/module.rs @@ -109,6 +109,7 @@ impl WebServerModule { } } + /// set the data for this module, this function will replace the previous data pub fn data(self, data: D) -> WebServerModule { WebServerModule { apis: self.apis, @@ -118,6 +119,7 @@ impl WebServerModule { } } + /// set the middleware for this module, this function will replace the previous middleware pub fn middleware(self, middleware: MW) -> WebServerModule { WebServerModule { apis: self.apis, @@ -127,6 +129,7 @@ impl WebServerModule { } } + /// set the options for this module, this function will replace the previous options pub fn options(self, options: WebServerModuleOption) -> Self { WebServerModule { options, ..self } } @@ -173,6 +176,7 @@ impl Default for WebServerGrpcModule { #[cfg(feature = "web-server-grpc")] impl<_MW, _D> WebServerGrpcModule<_MW, _D> { + /// set the data for this module, this function will replace the previous data pub fn data(self, data: D) -> WebServerGrpcModule<_MW, D> { WebServerGrpcModule { data: Some(data), @@ -182,6 +186,7 @@ impl<_MW, _D> WebServerGrpcModule<_MW, _D> { } } + /// set the middleware for this module, this function will replace the previous middleware pub fn middleware(self, middleware: MW) -> WebServerGrpcModule { WebServerGrpcModule { data: self.data, @@ -194,6 +199,7 @@ impl<_MW, _D> WebServerGrpcModule<_MW, _D> { #[cfg(feature = "web-server-grpc")] impl WebServerGrpcModule { + /// with new grpc service T, T must be a [`poem_grpc::Service`] pub fn with_grpc_service(mut self, service: T) -> Self where T: poem::IntoEndpoint> + poem_grpc::Service + Send + Sync + 'static, @@ -202,6 +208,8 @@ impl WebServerGrpcModule { self.grpc_router_mapper = Arc::new(move |route| previous_mapper(route).add_service(service.clone())); self } + + /// with grpc descriptor pub fn with_descriptor(mut self, descriptor: Vec) -> Self { self.descriptor_sets.push(descriptor); self