tarantool_rs/client/
executor.rs

1use std::fmt::Debug;
2
3use async_trait::async_trait;
4use rmpv::Value;
5
6use crate::{
7    client::{private::Sealed, Stream, Transaction, TransactionBuilder},
8    codec::request::EncodedRequest,
9    Result,
10};
11
12/// Type, which can make requests to Tarantool and create streams and transactions.
13#[async_trait]
14pub trait Executor: Sealed + Send + Sync + Debug {
15    /// Send encoded request.
16    async fn send_encoded_request(&self, request: EncodedRequest) -> Result<Value>;
17
18    /// Get new [`Stream`].
19    ///
20    /// It is safe to create `Stream` from any type, implementing current trait.
21    fn stream(&self) -> Stream;
22
23    /// Prepare [`TransactionBuilder`], which can be used to override parameters and create
24    /// [`Transaction`].
25    ///
26    /// It is safe to create `TransactionBuilder` from any type.
27    fn transaction_builder(&self) -> TransactionBuilder;
28
29    /// Create [`Transaction`] with parameters from builder.
30    ///
31    /// It is safe to create `Transaction` from any type, implementing current trait.
32    async fn transaction(&self) -> Result<Transaction>;
33
34    async fn get_cached_sql_statement_id(&self, statement: &str) -> Option<u64>;
35}
36
37#[async_trait]
38impl<E: Executor + Sealed + Sync + Debug> Executor for &E {
39    async fn send_encoded_request(&self, request: EncodedRequest) -> Result<Value> {
40        (**self).send_encoded_request(request).await
41    }
42
43    fn stream(&self) -> Stream {
44        (**self).stream()
45    }
46
47    fn transaction_builder(&self) -> TransactionBuilder {
48        (**self).transaction_builder()
49    }
50
51    async fn transaction(&self) -> Result<Transaction> {
52        (**self).transaction().await
53    }
54
55    async fn get_cached_sql_statement_id(&self, statement: &str) -> Option<u64> {
56        (**self).get_cached_sql_statement_id(statement).await
57    }
58}
59
60#[async_trait]
61impl<E: Executor + Sealed + Sync + Debug> Executor for &mut E {
62    async fn send_encoded_request(&self, request: EncodedRequest) -> Result<Value> {
63        (**self).send_encoded_request(request).await
64    }
65
66    fn stream(&self) -> Stream {
67        (**self).stream()
68    }
69
70    fn transaction_builder(&self) -> TransactionBuilder {
71        (**self).transaction_builder()
72    }
73
74    async fn transaction(&self) -> Result<Transaction> {
75        (**self).transaction().await
76    }
77
78    async fn get_cached_sql_statement_id(&self, statement: &str) -> Option<u64> {
79        (**self).get_cached_sql_statement_id(statement).await
80    }
81}
82
83#[cfg(test)]
84mod ui {
85    use super::*;
86    use crate::ExecutorExt;
87
88    #[test]
89    fn executor_trait_object_safety() {
90        fn _f(executor: impl Executor) {
91            let _: Box<dyn Executor> = Box::new(executor);
92        }
93    }
94
95    #[test]
96    fn calling_conn_like_on_dyn_executor() {
97        async fn _f(conn: &dyn Executor) -> Result<()> {
98            conn.ping().await
99        }
100    }
101
102    #[test]
103    fn calling_conn_like_on_boxed_dyn_executor() {
104        async fn _f(conn: &Box<dyn Executor>) -> Result<()> {
105            conn.ping().await
106        }
107    }
108}