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    /// Construct a proxy session from an AsyncClient or Client object and a
29    /// `handle_request` callback.  The callback should ultimately invoke
30    /// `handle_request` on another client, passing along the argument
31    /// passed to it.
32    #[new]
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
44        let callback = {
45            move |msg: &[u8]| {
46                let msg = msg.to_vec();
47                Python::with_gil(|py| {
48                    let bytes = PyBytes::new(py, &msg);
49                    handle_request.call1(py, (bytes,))?;
50                    Ok(())
51                })
52            }
53        };
54
55        Ok(ProxySession(perspective_client::ProxySession::new(
56            client, callback,
57        )))
58    }
59
60    pub fn handle_request(&self, py: Python<'_>, data: Vec<u8>) -> PyResult<()> {
61        self.0.handle_request(&data).py_block_on(py).into_pyerr()?;
62        Ok(())
63    }
64
65    pub async fn handle_request_async(&self, data: Vec<u8>) -> PyResult<()> {
66        self.0.handle_request(&data).await.into_pyerr()?;
67        Ok(())
68    }
69
70    pub fn close(&self, py: Python<'_>) -> PyResult<()> {
71        self.0.clone().close().py_block_on(py);
72        Ok(())
73    }
74}