I find myself playing around with warp.
I would like to pass a database Trait to a warp::Filter using static dispatch, such that the concrete database may vary.
I read that Send + Sync are unsafe to implement, but I don't fully understand when it is appropriate to implement them.
Is it sound to implement Send + Sync in this context:
use std::sync::{Arc, RwLock};
use warp::Filter;
use warp::reply::{json};
use serde_json::{Value};
pub trait IDatabase {
fn db_read(&self) -> Value;
fn db_write(&self, data: Value);
}
pub fn get_api_v0_test<T: IDatabase + Send + Sync>(
db: Arc<RwLock<T>>
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
warp::path!("api" / "v0" / "test")
.and(warp::get())
.map(move || {
json(&db.read().unwrap().db_read())
})
}
Edit:
Yes, this example is completely sound!
As @trentcl and @Masklinn pointed out, I am in fact not implementing Send + Sync, I am simply requiring that any type T passed into the filter, implements the Send + Sync Traits, which is completely safe Rust.
Because
Send
andSync
are automatically derived, it is only appropriate to derive them explicitely when wrapping raw pointers, usually because you're wrapping a native library, and after having made sure that the trait is appropriate for the underlying type.I don't understand what you'd want to "implement Send + Sync" on in this context.
Rust is not C#,
IWhatever
is not a thing.