9个版本 (4个破坏性更新)
0.5.3 | 2024年1月29日 |
---|---|
0.5.2 | 2024年1月29日 |
0.4.1 | 2024年1月26日 |
0.3.0 | 2024年1月14日 |
0.1.0 | 2024年1月13日 |
#1438 在 过程宏
每月22次 下载
在 pg_sgr_from_row 中使用
43KB
1K SLoC
SyncA
SyncA是一个用于创建同时具有同步和异步版本的crate的框架。
文档
动机
当我们编写一个库时,我们无法控制我们的代码将被使用的环境。
这通常导致只有同步版本,或者两个不同的crate。第一个解决方案的问题很明显,而第二个则违反了DRY原则。
SyncA通过创建模块的副本来解决此问题。
概念
将synca宏属性应用于要复制的模块。作为参数,它接受基于模板应创建的模块。
在模块体中,可以描述代码修饰符。
代码修饰符
- sync - 将模块代码转换为同步版本
- replace - 替换类型和属性
示例
#[synca::synca(
#[cfg(feature = "tokio")]
pub mod tokio { },
#[cfg(feature = "sync")]
pub mod sync {
sync!();
replace!(
tokio_postgres::Client => postgres::Client,
tokio_postgres::Error => postgres::Error,
tokio_postgres::NoTls => postgres::NoTls,
#[tokio::test] => #[test]
);
}
)]
mod my_mod {
struct MyStruct {
client: tokio_postgres::Client
}
pub async fn get_name(client: &mut tokio_postgres::Client) -> String {
let row = self.client.query_one("SQL", &[]).await.unwrap();
row.get("name")
}
#[cfg(test)]
mod tests {
use super::get_name;
#[tokio::test]
pub async fn get_name_test() {
assert_eq!(get_name(&mut client()).await, "My name");
}
fn client() -> tokio_postgres::Client {
#[synca::cfg(tokio)]
let (client, connection) = tokio_postgres::connect("CONNECTION_STRING", tokio_postgres::NoTls).await?;
#[synca::cfg(tokio)]
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
#[synca::cfg(sync)]
let client = postgres::Client::connect(&conn_str, postgres::NoTls)?;
client
}
}
}
生成的代码
#[cfg(feature = "tokio")]
pub mod tokio {
struct MyStruct {
client: tokio_postgres::Client
}
pub async fn get_name(client: &mut tokio_postgres::Client) -> String {
let row = self.client.query_one("SQL", &[]).await.unwrap();
row.get("name")
}
#[cfg(test)]
mod tests {
use super::get_name;
#[tokio::test]
pub async fn get_name_test() {
assert_eq!(get_name(&mut client()).await, "My name");
}
fn client() -> tokio_postgres::Client {
let (client, connection) = tokio_postgres::connect("CONNECTION_STRING", tokio_postgres::NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
#[сfg(all(feature = "tokio", not(feature = "tokio")))]
let client = postgres::Client::connect(&conn_str, postgres::NoTls)?;
client
}
}
}
#[cfg(feature = "sync")]
mod sync {
struct MyStruct {
client: postgres::Client
}
pub fn get_name(client: &mut postgres::Client) -> String {
let row = self.client.query_one("SQL", &[]).unwrap();
row.get("name")
}
#[cfg(test)]
mod tests {
use super::get_name;
#[test]
pub async fn get_name_test() {
assert_eq!(get_name(&mut client()), "My name");
}
fn client() -> postgres::Client {
#[сfg(all(feature = "tokio", not(feature = "tokio")))]
let (client, connection) = tokio_postgres::connect("CONNECTION_STRING", tokio_postgres::NoTls).await?;
#[сfg(all(feature = "tokio", not(feature = "tokio")))]
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
let client = postgres::Client::connect(&conn_str, postgres::NoTls)?;
client
}
}
}
依赖关系
~260–700KB
~17K SLoC