You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

70 lines
2.0 KiB

//! common facade & shim helpers
use bt_facade_proto::common::Data;
use bt_packets::hci::Packet;
use futures::sink::SinkExt;
use grpcio::*;
use std::sync::Arc;
use tokio::runtime::Runtime;
use tokio::sync::mpsc::Receiver;
use tokio::sync::Mutex;
/// Wrapper so we can invoke callbacks
pub trait U8SliceRunnable {
/// Do the thing
fn run(&self, data: &[u8]);
}
/// Helper for interfacing channels with shim or gRPC boundaries
#[derive(Clone)]
pub struct RxAdapter<T> {
rx: Arc<Mutex<Receiver<T>>>,
running: bool,
}
impl<T: 'static + Packet + Send> RxAdapter<T> {
/// New, from an unwrapped receiver
pub fn new(rx: Receiver<T>) -> Self {
Self::from_arc(Arc::new(Mutex::new(rx)))
}
/// New, from an already arc mutexed receiver
pub fn from_arc(rx: Arc<Mutex<Receiver<T>>>) -> Self {
Self { rx, running: false }
}
/// Stream out the channel over the provided sink
pub fn stream_grpc(&mut self, ctx: RpcContext<'_>, mut sink: ServerStreamingSink<Data>) {
assert!(!self.running);
self.running = true;
let clone_rx = self.rx.clone();
ctx.spawn(async move {
while let Some(payload) = clone_rx.lock().await.recv().await {
let mut data = Data::default();
data.set_payload(payload.to_vec());
if let Err(e) = sink.send((data, WriteFlags::default())).await {
log::error!("failure sending data: {:?}", e);
}
}
});
}
/// Stream out the channel over the provided shim runnable
pub fn stream_runnable<R: 'static + U8SliceRunnable + Send>(
&mut self,
rt: &Arc<Runtime>,
runnable: R,
) {
assert!(!self.running);
self.running = true;
let clone_rx = self.rx.clone();
rt.spawn(async move {
while let Some(payload) = clone_rx.lock().await.recv().await {
runnable.run(&payload.to_bytes());
}
});
}
}