forked from auracaster/bumble_mirror
93 lines
3.3 KiB
Rust
93 lines
3.3 KiB
Rust
// Copyright 2023 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! L2CAP
|
|
|
|
use crate::wrapper::{ClosureCallback, PyObjectExt};
|
|
use pyo3::{intern, PyObject, PyResult, Python};
|
|
|
|
/// L2CAP connection-oriented channel
|
|
pub struct LeConnectionOrientedChannel(PyObject);
|
|
|
|
impl LeConnectionOrientedChannel {
|
|
/// Create a LeConnectionOrientedChannel that wraps the provided obj.
|
|
pub(crate) fn from(obj: PyObject) -> Self {
|
|
Self(obj)
|
|
}
|
|
|
|
/// Queues data to be automatically sent across this channel.
|
|
pub fn write(&mut self, data: &[u8]) -> PyResult<()> {
|
|
Python::with_gil(|py| self.0.call_method1(py, intern!(py, "write"), (data,))).map(|_| ())
|
|
}
|
|
|
|
/// Wait for queued data to be sent on this channel.
|
|
pub async fn drain(&mut self) -> PyResult<()> {
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.call_method0(py, intern!(py, "drain"))
|
|
.and_then(|coroutine| pyo3_asyncio::tokio::into_future(coroutine.as_ref(py)))
|
|
})?
|
|
.await
|
|
.map(|_| ())
|
|
}
|
|
|
|
/// Register a callback to be called when the channel is closed.
|
|
pub fn on_close(
|
|
&mut self,
|
|
callback: impl Fn(Python) -> PyResult<()> + Send + 'static,
|
|
) -> PyResult<()> {
|
|
let boxed = ClosureCallback::new(move |py, _args, _kwargs| callback(py));
|
|
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.call_method1(py, intern!(py, "add_listener"), ("close", boxed))
|
|
})
|
|
.map(|_| ())
|
|
}
|
|
|
|
/// Register a callback to be called when the channel receives data.
|
|
pub fn set_sink(
|
|
&mut self,
|
|
callback: impl Fn(Python, &[u8]) -> PyResult<()> + Send + 'static,
|
|
) -> PyResult<()> {
|
|
let boxed = ClosureCallback::new(move |py, args, _kwargs| {
|
|
callback(py, args.get_item(0)?.extract()?)
|
|
});
|
|
Python::with_gil(|py| self.0.setattr(py, intern!(py, "sink"), boxed)).map(|_| ())
|
|
}
|
|
|
|
/// Disconnect the l2cap channel.
|
|
/// Must be called from a thread with a Python event loop, which should be true on
|
|
/// `tokio::main` and `async_std::main`.
|
|
///
|
|
/// For more info, see <https://awestlake87.github.io/pyo3-asyncio/master/doc/pyo3_asyncio/#event-loop-references-and-contextvars>.
|
|
pub async fn disconnect(&mut self) -> PyResult<()> {
|
|
Python::with_gil(|py| {
|
|
self.0
|
|
.call_method0(py, intern!(py, "disconnect"))
|
|
.and_then(|coroutine| pyo3_asyncio::tokio::into_future(coroutine.as_ref(py)))
|
|
})?
|
|
.await
|
|
.map(|_| ())
|
|
}
|
|
|
|
/// Returns some information about the channel as a [String].
|
|
pub fn debug_string(&self) -> PyResult<String> {
|
|
Python::with_gil(|py| {
|
|
let str_obj = self.0.call_method0(py, intern!(py, "__str__"))?;
|
|
str_obj.gil_ref(py).extract()
|
|
})
|
|
}
|
|
}
|