use std::fmt::Debug;
use log::{trace, warn};
use tokio::sync::mpsc::Sender;
use super::decoder::Decoder;
use crate::error::Error;
use crate::frame::{Callback, Frame, Parameters};
pub struct Splitter {
incoming: Decoder,
responses: Sender<Result<Parameters, Error>>,
callbacks: Sender<Callback>,
}
impl Splitter {
#[must_use]
pub const fn new(
incoming: Decoder,
responses: Sender<Result<Parameters, Error>>,
callbacks: Sender<Callback>,
) -> Self {
Self {
incoming,
responses,
callbacks,
}
}
pub async fn run(mut self) {
while let Some(frame) = self.incoming.decode().await {
match frame {
Ok(frame) => {
trace!("Received frame: {frame:?}");
self.handle_frame(frame).await;
}
Err(error) => {
warn!("Failed to decode frame: {error}");
self.responses
.send(Err(error))
.await
.expect("Response channel should be open. This is a bug.");
}
}
}
}
async fn handle_frame(&self, frame: Frame) {
let (header, parameters) = frame.into();
match parameters {
Parameters::Response(response) => {
trace!("Forwarding response: {response:?}");
self.handle_response(Parameters::Response(response)).await;
}
Parameters::Callback(callback) => {
if header.is_async_callback() {
trace!("Forwarding async callback: {callback:?}");
self.handle_callback(callback).await;
} else {
trace!("Forwarding non-async callback as response: {callback:?}");
self.handle_response(Parameters::Callback(callback)).await;
}
}
}
}
async fn handle_response(&self, parameters: Parameters) {
self.responses
.send(Ok(parameters))
.await
.expect("Response channel should be open. This is a bug.");
}
async fn handle_callback(&self, handler: Callback) {
self.callbacks
.send(handler)
.await
.expect("Callback channel should be open. This is a bug");
}
}
impl Debug for Splitter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Splitter")
.field("incoming", &self.incoming)
.field("responses", &self.responses)
.field("callbacks", &"...")
.finish()
}
}