odoo_api/client/http_impl/
closure_async.rs

1use crate::client::error::{ClosureAuthResult, ClosureError, ClosureResult};
2use crate::client::{AuthState, Authed, NotAuthed, OdooClient, OdooRequest, RequestImpl};
3use crate::jsonrpc::JsonRpcParams;
4use serde::Serialize;
5use serde_json::{to_value, Value};
6use std::fmt::Debug;
7use std::future::Future;
8use std::pin::Pin;
9
10/// Convenience typedef. Use this as the return value for your async closure
11pub type ClosureReturn = Pin<Box<dyn Future<Output = ClosureResult<(String, Option<String>)>>>>;
12type Closure = Box<dyn Fn(String, Value, Option<String>) -> ClosureReturn>;
13
14pub struct ClosureAsync {
15    closure: Closure,
16}
17impl RequestImpl for ClosureAsync {
18    type Error = ClosureError;
19}
20
21impl OdooClient<NotAuthed, ClosureAsync> {
22    pub fn new_closure_async(
23        url: &str,
24        closure: impl 'static
25            + Fn(
26                String,
27                Value,
28                Option<String>,
29            )
30                -> Pin<Box<dyn Future<Output = ClosureResult<(String, Option<String>)>>>>,
31    ) -> Self {
32        Self::new(
33            url,
34            ClosureAsync {
35                closure: Box::new(closure),
36            },
37        )
38    }
39}
40
41impl<S> OdooClient<S, ClosureAsync>
42where
43    S: AuthState,
44{
45    pub async fn authenticate(
46        mut self,
47        db: &str,
48        login: &str,
49        password: &str,
50    ) -> ClosureAuthResult<OdooClient<Authed, ClosureAsync>> {
51        let request = self.get_auth_request(db, login, password);
52        let (response, session_id) = request.send_internal().await?;
53        Ok(self.parse_auth_response(db, login, password, response, session_id)?)
54    }
55}
56
57impl<'a, T> OdooRequest<'a, T, ClosureAsync>
58where
59    T: JsonRpcParams + Debug + Serialize,
60    T::Container<T>: Debug + Serialize,
61{
62    pub async fn send(self) -> ClosureResult<T::Response> {
63        Ok(self.send_internal().await?.0)
64    }
65
66    async fn send_internal(self) -> ClosureResult<(T::Response, Option<String>)> {
67        let data = to_value(&self.data)?;
68        let (response, session_id) = (self._impl.closure)(
69            self.url.clone(),
70            data,
71            self.session_id.map(|s| s.to_string()),
72        )
73        .await?;
74        Ok((self.parse_response(&response)?, session_id))
75    }
76}