Merge pull request #555 from teloxide/erased-storage

Implement `ErasedStorage`
This commit is contained in:
Hirrolot 2022-03-21 05:17:11 -07:00 committed by GitHub
commit c2c5e463fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 2 deletions

View file

@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## unreleased
### Added
- The `Storage::erase` default function that returns `ErasedStorage`.
- `ErasedStorage`, a storage with an erased error type.
## 0.7.1 - 2022-03-09
### Fixed

View file

@ -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::*;

View file

@ -72,4 +72,79 @@ pub trait Storage<D> {
self: Arc<Self>,
chat_id: i64,
) -> BoxFuture<'static, Result<Option<D>, Self::Error>>;
/// Erases [`Self::Error`] to [`std::error::Error`].
fn erase(self: Arc<Self>) -> ErasedStorage<D>
where
Self: Sized + Send + Sync + 'static,
Self::Error: std::error::Error + 'static,
{
struct Eraser<S>(Arc<S>);
impl<D, S> Storage<D> for Eraser<S>
where
S: Storage<D> + Send + Sync + 'static,
S::Error: std::error::Error + 'static,
{
type Error = Box<dyn std::error::Error>;
fn remove_dialogue(
self: Arc<Self>,
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<Self>,
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<Self>,
chat_id: i64,
) -> BoxFuture<'static, Result<Option<D>, Self::Error>> {
Box::pin(async move {
Arc::clone(&self.0).get_dialogue(chat_id).await.map_err(|e| e.into())
})
}
}
Arc::new(Eraser(self))
}
}
/// A storage with an erased error type.
pub type ErasedStorage<D> = Arc<dyn Storage<D, Error = Box<dyn std::error::Error>>>;
#[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);
}
}

View file

@ -92,7 +92,7 @@ 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, TraceStorage,
};
pub use get_chat_id::GetChatId;