From c6f0cd94049bc3a127e1f1afdda6520e1ecf9286 Mon Sep 17 00:00:00 2001 From: Hirrolot Date: Sun, 20 Mar 2022 09:06:21 +0600 Subject: [PATCH] Implement `ErasedStorage` --- CHANGELOG.md | 5 ++ src/dispatching/dialogue/mod.rs | 2 +- src/dispatching/dialogue/storage/mod.rs | 82 +++++++++++++++++++++++++ src/dispatching2/dialogue/mod.rs | 3 +- 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f67379..aaaf25d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## unreleased +### Added + +- The `StorageExt` trait with a single function `erase` that returns `ErasedStorage`. +- `ErasedStorage`, a storage with an erased error type. + ## 0.7.1 - 2022-03-09 ### Fixed diff --git a/src/dispatching/dialogue/mod.rs b/src/dispatching/dialogue/mod.rs index 3f336d73..8c6e6bae 100644 --- a/src/dispatching/dialogue/mod.rs +++ b/src/dispatching/dialogue/mod.rs @@ -169,4 +169,4 @@ pub use storage::{RedisStorage, RedisStorageError}; #[cfg(feature = "sqlite-storage")] pub use storage::{SqliteStorage, SqliteStorageError}; -pub use storage::{serializer, InMemStorage, InMemStorageError, Serializer, Storage, TraceStorage}; +pub use storage::*; diff --git a/src/dispatching/dialogue/storage/mod.rs b/src/dispatching/dialogue/storage/mod.rs index 506e18bf..c20855ed 100644 --- a/src/dispatching/dialogue/storage/mod.rs +++ b/src/dispatching/dialogue/storage/mod.rs @@ -73,3 +73,85 @@ pub trait Storage { chat_id: i64, ) -> BoxFuture<'static, Result, Self::Error>>; } + +/// A storage with an erased error type. +pub type ErasedStorage = Arc>>; + +/// Extension methods for working with [`Storage`]. +pub trait StorageExt { + /// Returns [`ErasedStorage`]. + fn erase(self: Arc) -> ErasedStorage; +} + +impl StorageExt for S +where + S: Storage + Send + Sync + 'static, + S::Error: std::error::Error + 'static, +{ + fn erase(self: Arc) -> ErasedStorage { + struct Eraser(Arc); + + impl Storage for Eraser + where + S: Storage + Send + Sync + 'static, + S::Error: std::error::Error + 'static, + { + type Error = Box; + + fn remove_dialogue( + self: Arc, + chat_id: i64, + ) -> BoxFuture<'static, Result<(), Self::Error>> + where + D: Send + 'static, + { + Box::pin(async move { + Arc::clone(&self.0).remove_dialogue(chat_id).await.map_err(|e| e.into()) + }) + } + + fn update_dialogue( + self: Arc, + chat_id: i64, + dialogue: D, + ) -> BoxFuture<'static, Result<(), Self::Error>> + where + D: Send + 'static, + { + Box::pin(async move { + Arc::clone(&self.0) + .update_dialogue(chat_id, dialogue) + .await + .map_err(|e| e.into()) + }) + } + + fn get_dialogue( + self: Arc, + chat_id: i64, + ) -> BoxFuture<'static, Result, Self::Error>> { + Box::pin(async move { + Arc::clone(&self.0).get_dialogue(chat_id).await.map_err(|e| e.into()) + }) + } + } + + Arc::new(Eraser(self)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_erased() { + let chat_id = 123; + + let erased = InMemStorage::new().erase(); + Arc::clone(&erased).update_dialogue(chat_id, 1).await.unwrap(); + assert_eq!(Arc::clone(&erased).get_dialogue(chat_id).await.unwrap().unwrap(), 1); + Arc::clone(&erased).remove_dialogue(chat_id).await.unwrap(); + assert_eq!(Arc::clone(&erased).get_dialogue(chat_id).await.unwrap(), None); + } +} diff --git a/src/dispatching2/dialogue/mod.rs b/src/dispatching2/dialogue/mod.rs index cf9867ed..a492b77c 100644 --- a/src/dispatching2/dialogue/mod.rs +++ b/src/dispatching2/dialogue/mod.rs @@ -92,7 +92,8 @@ pub use crate::dispatching::dialogue::{RedisStorage, RedisStorageError}; pub use crate::dispatching::dialogue::{SqliteStorage, SqliteStorageError}; pub use crate::dispatching::dialogue::{ - serializer, InMemStorage, InMemStorageError, Serializer, Storage, TraceStorage, + serializer, ErasedStorage, InMemStorage, InMemStorageError, Serializer, Storage, StorageExt, + TraceStorage, }; pub use get_chat_id::GetChatId;