perspective_python/client/
proxy_session.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use perspective_client::Session;
14use pyo3::exceptions::PyTypeError;
15use pyo3::prelude::*;
16use pyo3::types::*;
17
18use super::client_async::AsyncClient;
19use super::client_sync::{Client as SyncClient, PyFutureExt};
20use crate::py_err::ResultTClientErrorExt;
21
22#[pyclass(module = "perspective")]
23#[derive(Clone)]
24pub struct ProxySession(perspective_client::ProxySession);
25
26#[pymethods]
27impl ProxySession {
28    #[new]
29    /// Construct a proxy session from an AsyncClient or Client object and a
30    /// `handle_request`` callback.  The callback should ultimately invoke
31    /// `handle_request` on another client, passing along the argument
32    /// passed to it.
33    fn new(py: Python<'_>, client: Py<PyAny>, handle_request: Py<PyAny>) -> PyResult<Self> {
34        let client = if let Ok(py_client) = client.downcast_bound::<AsyncClient>(py) {
35            py_client.borrow().client.clone()
36        } else if let Ok(py_client) = client.downcast_bound::<SyncClient>(py) {
37            py_client.borrow().0.client.clone()
38        } else {
39            return Err(PyTypeError::new_err(
40                "ProxySession::new() not passed a Perspective client",
41            ));
42        };
43        let callback = {
44            move |msg: &[u8]| {
45                let msg = msg.to_vec();
46                Python::with_gil(|py| {
47                    let bytes = PyBytes::new(py, &msg);
48                    handle_request.call1(py, (bytes,))?;
49                    Ok(())
50                })
51            }
52        };
53
54        Ok(ProxySession(perspective_client::ProxySession::new(
55            client, callback,
56        )))
57    }
58
59    pub fn handle_request(&self, py: Python<'_>, data: Vec<u8>) -> PyResult<()> {
60        self.0.handle_request(&data).py_block_on(py).into_pyerr()?;
61        Ok(())
62    }
63
64    pub async fn handle_request_async(&self, data: Vec<u8>) -> PyResult<()> {
65        self.0.handle_request(&data).await.into_pyerr()?;
66        Ok(())
67    }
68
69    pub fn poll(&self, py: Python<'_>) -> PyResult<()> {
70        self.0.poll().py_block_on(py).into_pyerr()?;
71        Ok(())
72    }
73
74    pub fn close(&self, py: Python<'_>) -> PyResult<()> {
75        self.0.clone().close().py_block_on(py);
76        Ok(())
77    }
78}