Skip to content

Commit

Permalink
higher-ranked trait bounds are broken, especially when returning future
Browse files Browse the repository at this point in the history
This is waiting on rust-lang/rust#70263
  • Loading branch information
fmeef committed Apr 10, 2022
1 parent f04701b commit df3b38c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 28 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bobot_impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ pomelo = "0.1.5"
regex = "1"
flexi_logger = { version = "0.22", features = [ "async", "colors" ] }
teloxide = { version = "0.7", features = ["macros", "auto-send", "redis-storage", "erased"] }
higher-order-closure = "0.0.5"
11 changes: 9 additions & 2 deletions bobot_impl/src/modules/sticker.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::str::FromStr;

use self::entities::tags::ModelRedis;
use crate::persist::redis::{scope_key_by_chatuser, CachedQuery, CachedQueryTrait, RedisStr};
use crate::persist::redis::{
scope_key_by_chatuser, CachedQuery, CachedQueryTrait, RedisPool, RedisStr,
};
use crate::persist::Result;
use crate::statics::{DB, REDIS, TG};
use crate::tg::command::{parse_cmd, Arg};
Expand All @@ -22,6 +24,8 @@ use teloxide::types::{
MessageCommon, MessageKind, Update, UpdateKind,
};

use higher_order_closure;

// redis keys
const KEY_TYPE_TAG: &str = "wc:tag";
const KEY_TYPE_STICKER_ID: &str = "wc:stickerid";
Expand Down Expand Up @@ -244,7 +248,10 @@ async fn handle_inline(query: &InlineQuery) -> Result<()> {
Ok(Some(stickers))
}
})
.redis_query(|key, redis| async move { Ok(None) })
.redis_query(|key: &_, redis: &_| async move {
println!("key{}", key);
Ok(None)
})
.build()?
.query(
Arc::clone(DB.deref()),
Expand Down
25 changes: 13 additions & 12 deletions bobot_impl/src/persist/redis.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use super::Result;
use crate::util::{
callback::{CacheCallback, CacheCb, CacheMissCallback, CacheMissCb, OutputBoxer},
callback::{
BotDbFuture, BoxedCacheCallback, CacheCallback, CacheCb, CacheMissCallback, CacheMissCb,
OutputBoxer,
},
error::BotError,
};
use anyhow::anyhow;
Expand All @@ -12,6 +15,7 @@ use bb8_redis::RedisConnectionManager;

use async_trait::async_trait;
use futures::Future;
use higher_order_closure::higher_order_closure;
use redis::{AsyncCommands, ErrorKind, FromRedisValue, Pipeline, RedisError, ToRedisArgs};
use serde::{de::DeserializeOwned, Serialize};
use std::sync::Arc;
Expand Down Expand Up @@ -39,24 +43,21 @@ pub(crate) struct CachedQueryBuilder<R> {
}

impl<R> CachedQueryBuilder<R> {
pub(crate) fn redis_query<F, Fut>(mut self, func: F) -> Self
pub(crate) fn redis_query<'a, F>(mut self, func: F) -> Self
where
F: for<'b> FnOnce(&'b String, &'b RedisPool) -> Fut + Sync + Send + 'static,
R: DeserializeOwned + 'static,
Fut: Future<Output = Result<Option<R>>> + Send + 'static,
F: for<'b> CacheCallback<'b, RedisPool, R> + 'static,
{
let b = Box::new(OutputBoxer(func));
self.redis_query = Some(CacheCb(b));
// self.redis_query = Some(CacheCb::new(func));
self
}

pub(crate) fn sql_query<F, Fut>(mut self, func: F) -> Self
pub(crate) fn sql_query<'a, F, Fut>(mut self, func: F) -> Self
where
F: for<'b> FnOnce(&'b String, &'b Arc<DatabaseConnection>) -> Fut + Sync + Send + 'static,
R: DeserializeOwned + 'static,
Fut: Future<Output = Result<Option<R>>> + Send + 'static,
F: for<'b> FnOnce(&'b String, &'b Arc<DatabaseConnection>) -> Fut + Sync + Send + 'a,
R: DeserializeOwned + 'a,
Fut: Future<Output = Result<Option<R>>> + Send + 'a,
{
self.sql_query = Some(CacheCb(Box::new(OutputBoxer(func))));
//self.sql_query = Some(CacheCb(Box::new(OutputBoxer(func))));
self
}

Expand Down
42 changes: 28 additions & 14 deletions bobot_impl/src/util/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,57 +23,71 @@ pub(crate) struct CacheCb<T, R>(
pub(crate) Box<dyn for<'a> BoxedCacheCallback<'a, T, R, Fut = BotDbFuture<'a, Result<Option<R>>>>>,
);

impl <'a, T, R: 'a> CacheCb<T, R> {

pub(crate) fn new<F>(func: F) -> Self
where
F: for<'b> CacheCallback<'b, T, R> + 'static,
R: DeserializeOwned + 'static
{
Self(Box::new(OutputBoxer(func)))

}
}

impl<'a, T, R> CacheCallback<'a, T, R> for CacheCb<T, R>
where
R: DeserializeOwned + 'static,
R: DeserializeOwned + 'a,
{
type Fut = BotDbFuture<'a, Result<Option<R>>>;
fn cb(self, key: &String, db: &T) -> Self::Fut {
fn cb(self, key: &'a String, db: &'a T) -> Self::Fut {
self.0.cb_boxed(key, db)
}
}

pub trait CacheCallback<'a, T, R>: Send + Sync {
type Fut: Future<Output = Result<Option<R>>> + Send + 'a;
fn cb(self, key: &String, db: &T) -> Self::Fut;
fn cb(self, key: &'a String, db: &'a T) -> Self::Fut;
}

pub trait BoxedCacheCallback<'a, T, R>: Send + Sync {
type Fut: Future<Output = Result<Option<R>>> + Send + 'a;
fn cb_boxed(self: Box<Self>, key: &String, db: &T) -> Self::Fut;
fn cb_boxed(self: Box<Self>, key: &'a String, db: &'a T) -> Self::Fut;
}

impl<'a, F, T, R, Fut> CacheCallback<'a, T, R> for F
where
F: for<'b> FnOnce(&'b String, &'b T) -> Fut + Sync + Send + 'static,
R: DeserializeOwned + 'static,
Fut: Future<Output = Result<Option<R>>> + Send + 'static,
F: FnOnce(&'a String, &'a T) -> Fut + Sync + Send + 'a,
R: DeserializeOwned + 'a,
T: 'a,
Fut: Future<Output = Result<Option<R>>> + Send + 'a,
{
type Fut = Fut;
fn cb(self, key: &String, db: &T) -> Self::Fut {
fn cb(self, key: &'a String, db: &'a T) -> Self::Fut {
self(key, db)
}
}

impl<'a, F, T, R> BoxedCacheCallback<'a, T, R> for OutputBoxer<F>
where
F: CacheCallback<'a, T, R>,
R: 'a,
R: DeserializeOwned + 'a
{
type Fut = BotDbFuture<'a, Result<Option<R>>>;
fn cb_boxed(self: Box<Self>, key: &String, db: &T) -> Self::Fut {
fn cb_boxed(self: Box<Self>, key: &'a String, db: &'a T) -> Self::Fut {
(*self).0.cb(key, db).boxed()
}
}

impl<'a, F, T, R, Fut> BoxedCacheCallback<'a, T, R> for F
where
F: for<'b> FnOnce(&'b String, &'b T) -> Fut + Sync + Send + 'static,
R: DeserializeOwned + 'static,
Fut: Future<Output = Result<Option<R>>> + Send + 'static,
F: FnOnce(&'a String, &'a T) -> Fut + Sync + Send + 'a,
R: 'a,
T: 'a,
Fut: Future<Output = Result<Option<R>>> + Send + 'a,
{
type Fut = Fut;
fn cb_boxed(self: Box<Self>, key: &String, db: &T) -> Self::Fut {
fn cb_boxed(self: Box<Self>, key: &'a String, db: &'a T) -> Self::Fut {
(*self)(key, db)
}
}
Expand Down

0 comments on commit df3b38c

Please sign in to comment.