use zksync_concurrency::{ctx, sync};
use super::{FrameKind, ReadReusableStream, WriteReusableStream};
use crate::noise::bytes;
#[derive(Debug)]
pub(crate) struct ReadStream(pub(super) sync::ExclusiveLock<ReadReusableStream>);
#[derive(Debug)]
pub(crate) struct WriteStream(pub(super) sync::ExclusiveLock<WriteReusableStream>);
impl ReadStream {
pub(crate) async fn read_exact(
&mut self,
ctx: &ctx::Ctx,
buf: &mut bytes::Buffer,
) -> anyhow::Result<()> {
loop {
if self.0.close_received {
return Ok(());
}
let mut frame = match self.0.cache.take() {
Some(frame) => frame,
None => match self.0.recv.recv_or_disconnected(ctx).await? {
Ok(frame) => frame,
Err(sync::Disconnected) => return Ok(()),
},
};
match frame.header.frame_kind() {
FrameKind::OPEN => {
tracing::debug!("unexpected OPEN frame");
}
FrameKind::CLOSE => {
self.0.close_received = true;
}
FrameKind::DATA => {
let data = frame.data.as_mut().unwrap();
data.take(buf.push(data.as_slice()));
if data.len() > 0 {
self.0.cache = Some(frame);
}
if buf.capacity() == 0 {
return Ok(());
}
}
_ => unreachable!("Bad FrameKind"),
}
}
}
}
impl WriteStream {
pub(crate) async fn write_all(&mut self, ctx: &ctx::Ctx, buf: &[u8]) -> anyhow::Result<()> {
let mut offset = 0;
while offset < buf.len() {
if self.0.buffer.capacity() == 0 {
self.0.send_data(ctx).await?;
}
offset += self.0.buffer.push(&buf[offset..]);
}
Ok(())
}
#[allow(dead_code)]
pub(crate) async fn flush(&mut self, ctx: &ctx::Ctx) -> anyhow::Result<()> {
self.0.send_data(ctx).await?;
self.0.flush.notify_one();
Ok(())
}
}
#[derive(Debug)]
pub(crate) struct Stream {
pub(crate) read: ReadStream,
pub(crate) write: WriteStream,
}