use std::{cmp::max, io::{self, Read, Write}};
use crate::{stream::Transport, codec::{Frame, FrameBuf, FrameKind}};
pub mod pull_t;
pub mod push_t;
pub(crate) trait Socket
where
Self: Sized,
{
fn bind(address: &str) -> io::Result<Self>;
fn connect(address: &str) -> io::Result<Self>;
fn transport(&mut self) -> &mut Transport;
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.transport().read(buf)
}
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.transport().write(buf)
}
#[inline]
fn send<I, S>(&mut self, mut data: I) -> io::Result<()>
where
I: DoubleEndedIterator<Item = S>,
S: std::fmt::Debug + AsRef<[u8]>,
{
let tail = data.next_back().expect("Can not send empty frame.");
let body: Vec<_> = data.collect();
let mut frame = Vec::with_capacity(max(
body.iter().map(|i| i.as_ref().len()).max().unwrap_or(0),
tail.as_ref().len(),
));
for part in body {
let size = part.as_ref().len();
if size <= std::u8::MAX as usize {
frame.push(0x01);
frame.push(size as u8);
} else {
frame.push(0x03);
frame.extend_from_slice(&(size as u32).to_be_bytes() as &[_]);
};
frame.extend_from_slice(part.as_ref());
self.write(&frame)?;
frame.clear();
}
frame.push(0x00);
frame.push(tail.as_ref().len() as u8);
frame.extend_from_slice(&tail.as_ref());
self.write(&frame)?;
Ok(())
}
#[inline]
fn recv_frame(&mut self) -> io::Result<FrameBuf> {
let mut head = [0; 9];
let head_n = self.read(&mut head)?;
let phantom_frame = Frame::new(&head as &[_]);
let size = phantom_frame.size().unwrap();
let frame_buf = if size > head.len() {
let mut tail = Vec::with_capacity(size - head.len());
let tail_n = self.read(tail.as_mut_slice())?;
let mut data = head[..head_n].to_vec();
data.extend_from_slice(&tail.as_slice()[..tail_n]);
FrameBuf::new(data)
} else {
FrameBuf::new(head[..head_n].to_vec())
};
Ok(frame_buf)
}
fn recv_frame_into<'b>(&mut self, buf: &'b mut [u8]) -> io::Result<Frame<'b>> {
let n = self.read(buf)?;
let byte_slice = &buf[..n];
let frame_slice = Frame::new(byte_slice);
Ok(frame_slice)
}
#[inline]
fn recv(&mut self) -> io::Result<Vec<Vec<u8>>> {
let mut frames = vec![];
loop {
let frame_buf = self.recv_frame()?;
assert!(frame_buf.as_frame().kind().is_some());
if let Some(message) = frame_buf.as_frame().try_into_message() {
frames.push(message.body().to_vec());
if message.is_last() {
break;
}
} else {
assert!(matches!(
frame_buf.as_frame().kind(),
Some(FrameKind::Command)
));
panic!(
"Unexpected command frame! {:#?}",
frame_buf.as_frame().try_into_command()
);
}
}
Ok(frames)
}
}