pub(crate) mod fixture;
use pin_project_lite::pin_project;
use rama::telemetry::tracing;
use std::io;
use std::pin::Pin;
use std::task::{Context, Poll, ready};
use tokio::io::{AsyncRead, ReadBuf};
use tokio::sync::mpsc;
pin_project! {
#[derive(Debug)]
pub(crate) struct StreamReadHalf {
#[pin]
read_rx: mpsc::UnboundedReceiver<Vec<u8>>,
read_buffer: Vec<u8>,
}
}
impl StreamReadHalf {
pub(crate) fn new(read_rx: mpsc::UnboundedReceiver<Vec<u8>>) -> Self {
Self {
read_rx,
read_buffer: Vec::new(),
}
}
}
impl AsyncRead for StreamReadHalf {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
let mut this = self.as_mut().project();
if !this.read_buffer.is_empty() {
let to_read = std::cmp::min(this.read_buffer.len(), buf.remaining());
buf.put_slice(&this.read_buffer[..to_read]);
this.read_buffer.drain(..to_read);
return Poll::Ready(Ok(()));
}
match this.read_rx.as_mut().get_mut().try_recv() {
Ok(data) => {
let to_read = std::cmp::min(data.len(), buf.remaining());
buf.put_slice(&data[..to_read]);
if to_read < data.len() {
let remaining = &data[to_read..];
this.read_buffer.extend_from_slice(remaining);
}
Poll::Ready(Ok(()))
}
Err(mpsc::error::TryRecvError::Empty) => {
match ready!(this.read_rx.poll_recv(cx)) {
Some(data) => {
let to_read = std::cmp::min(data.len(), buf.remaining());
buf.put_slice(&data[..to_read]);
if to_read < data.len() {
let remaining = &data[to_read..];
this.read_buffer.extend_from_slice(remaining);
}
Poll::Ready(Ok(()))
}
None => Poll::Ready(Ok(())),
}
}
Err(mpsc::error::TryRecvError::Disconnected) => {
Poll::Ready(Ok(()))
}
}
}
}
pub(crate) fn init_tracing() {
use std::sync::Once;
static INIT: Once = Once::new();
INIT.call_once(|| {
drop(
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.with_target(true)
.with_thread_ids(true)
.with_thread_names(true)
.try_init(),
);
});
}