|
|
@ -13,401 +13,411 @@ use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; |
|
|
use super::prefix::Prefixer;
|
|
|
use super::prefix::Prefixer;
|
|
|
use super::u32::{decode_u32, U32_BYTE_LEN};
|
|
|
use super::u32::{decode_u32, U32_BYTE_LEN};
|
|
|
use super::value::{
|
|
|
use super::value::{
|
|
|
ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError, ValueEncoder,
|
|
|
|
|
|
|
|
|
ValueDecode, ValueDecodeError, ValueDecoder, ValueEncode, ValueEncodeError,
|
|
|
|
|
|
ValueEncoder,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
#[derive(Debug, Error, PartialEq)]
|
|
|
#[derive(Debug, Error, PartialEq)]
|
|
|
pub enum FrameEncodeError {
|
|
|
pub enum FrameEncodeError {
|
|
|
#[error("encoded value length {length} is too large")]
|
|
|
|
|
|
ValueTooLarge {
|
|
|
|
|
|
/// The length of the encoded value.
|
|
|
|
|
|
length: usize,
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
#[error("failed to encode value: {0}")]
|
|
|
|
|
|
ValueEncodeError(#[from] ValueEncodeError),
|
|
|
|
|
|
|
|
|
#[error("encoded value length {length} is too large")]
|
|
|
|
|
|
ValueTooLarge {
|
|
|
|
|
|
/// The length of the encoded value.
|
|
|
|
|
|
length: usize,
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
#[error("failed to encode value: {0}")]
|
|
|
|
|
|
ValueEncodeError(#[from] ValueEncodeError),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl From<FrameEncodeError> for io::Error {
|
|
|
impl From<FrameEncodeError> for io::Error {
|
|
|
fn from(error: FrameEncodeError) -> Self {
|
|
|
|
|
|
io::Error::new(io::ErrorKind::InvalidData, format!("{}", error))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
fn from(error: FrameEncodeError) -> Self {
|
|
|
|
|
|
io::Error::new(io::ErrorKind::InvalidData, format!("{}", error))
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Encodes entire protocol frames containing values of type `T`.
|
|
|
/// Encodes entire protocol frames containing values of type `T`.
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct FrameEncoder<T: ?Sized> {
|
|
|
pub struct FrameEncoder<T: ?Sized> {
|
|
|
phantom: PhantomData<T>,
|
|
|
|
|
|
|
|
|
phantom: PhantomData<T>,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<T: ValueEncode + ?Sized> FrameEncoder<T> {
|
|
|
impl<T: ValueEncode + ?Sized> FrameEncoder<T> {
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
phantom: PhantomData,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
phantom: PhantomData,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn encode_to(&mut self, value: &T, buffer: &mut BytesMut) -> Result<(), FrameEncodeError> {
|
|
|
|
|
|
let mut prefixer = Prefixer::new(buffer);
|
|
|
|
|
|
|
|
|
|
|
|
ValueEncoder::new(prefixer.suffix_mut()).encode(value)?;
|
|
|
|
|
|
|
|
|
pub fn encode_to(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
value: &T,
|
|
|
|
|
|
buffer: &mut BytesMut,
|
|
|
|
|
|
) -> Result<(), FrameEncodeError> {
|
|
|
|
|
|
let mut prefixer = Prefixer::new(buffer);
|
|
|
|
|
|
|
|
|
if let Err(prefixer) = prefixer.finalize() {
|
|
|
|
|
|
return Err(FrameEncodeError::ValueTooLarge {
|
|
|
|
|
|
length: prefixer.suffix().len(),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
ValueEncoder::new(prefixer.suffix_mut()).encode(value)?;
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
|
if let Err(prefixer) = prefixer.finalize() {
|
|
|
|
|
|
return Err(FrameEncodeError::ValueTooLarge {
|
|
|
|
|
|
length: prefixer.suffix().len(),
|
|
|
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Decodes entire protocol frames containing values of type `T`.
|
|
|
/// Decodes entire protocol frames containing values of type `T`.
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct FrameDecoder<T> {
|
|
|
pub struct FrameDecoder<T> {
|
|
|
// Only here to enable parameterizing `Decoder` by `T`.
|
|
|
|
|
|
phantom: PhantomData<T>,
|
|
|
|
|
|
|
|
|
// Only here to enable parameterizing `Decoder` by `T`.
|
|
|
|
|
|
phantom: PhantomData<T>,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<T: ValueDecode> FrameDecoder<T> {
|
|
|
impl<T: ValueDecode> FrameDecoder<T> {
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
phantom: PhantomData,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
phantom: PhantomData,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Attempts to decode an entire frame from the given buffer.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(Some(frame))` if successful, in which case the frame's bytes
|
|
|
|
|
|
/// have been split off from the left of `bytes`.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(None)` if not enough bytes are available to decode an entire
|
|
|
|
|
|
/// frame yet, in which case `bytes` is untouched.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns an error if the length prefix or the framed value are malformed,
|
|
|
|
|
|
/// in which case `bytes` is untouched.
|
|
|
|
|
|
pub fn decode_from(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
bytes: &mut BytesMut,
|
|
|
|
|
|
) -> Result<Option<T>, ValueDecodeError> {
|
|
|
|
|
|
if bytes.len() < U32_BYTE_LEN {
|
|
|
|
|
|
return Ok(None); // Not enough bytes yet.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Attempts to decode an entire frame from the given buffer.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(Some(frame))` if successful, in which case the frame's bytes
|
|
|
|
|
|
/// have been split off from the left of `bytes`.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(None)` if not enough bytes are available to decode an entire
|
|
|
|
|
|
/// frame yet, in which case `bytes` is untouched.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns an error if the length prefix or the framed value are malformed,
|
|
|
|
|
|
/// in which case `bytes` is untouched.
|
|
|
|
|
|
pub fn decode_from(&mut self, bytes: &mut BytesMut) -> Result<Option<T>, ValueDecodeError> {
|
|
|
|
|
|
if bytes.len() < U32_BYTE_LEN {
|
|
|
|
|
|
return Ok(None); // Not enough bytes yet.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Split the prefix off. After this:
|
|
|
|
|
|
//
|
|
|
|
|
|
// | bytes (len 4) | suffix |
|
|
|
|
|
|
//
|
|
|
|
|
|
// NOTE: This method would be simpler if we could use split_to() instead
|
|
|
|
|
|
// here such that `bytes` contained the suffix. At the end, we would not
|
|
|
|
|
|
// have to replace `bytes` with `suffix`. However, that would require
|
|
|
|
|
|
// calling `prefix.unsplit(*bytes)`, and that does not work since
|
|
|
|
|
|
// `bytes` is only borrowed, and unsplit() takes its argument by value.
|
|
|
|
|
|
let mut suffix = bytes.split_off(U32_BYTE_LEN);
|
|
|
|
|
|
|
|
|
|
|
|
// unwrap() cannot panic because `bytes` is of the exact right length.
|
|
|
|
|
|
let array: [u8; U32_BYTE_LEN] = bytes.as_ref().try_into().unwrap();
|
|
|
|
|
|
let length = decode_u32(array) as usize;
|
|
|
|
|
|
|
|
|
|
|
|
if suffix.len() < length {
|
|
|
|
|
|
// Re-assemble `bytes` as it first was.
|
|
|
|
|
|
bytes.unsplit(suffix);
|
|
|
|
|
|
return Ok(None); // Not enough bytes yet.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Split off the right amount of bytes from the buffer. After this:
|
|
|
|
|
|
//
|
|
|
|
|
|
// | bytes (len 4) | contents | suffix |
|
|
|
|
|
|
//
|
|
|
|
|
|
let mut contents = suffix.split_to(length);
|
|
|
|
|
|
|
|
|
|
|
|
// Attempt to decode the value.
|
|
|
|
|
|
let item = match ValueDecoder::new(&contents).decode() {
|
|
|
|
|
|
Ok(item) => item,
|
|
|
|
|
|
Err(error) => {
|
|
|
|
|
|
// Re-assemble `bytes` as it first was.
|
|
|
|
|
|
contents.unsplit(suffix);
|
|
|
|
|
|
bytes.unsplit(contents);
|
|
|
|
|
|
return Err(error);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the decoded bytes from the left of `bytes`.
|
|
|
|
|
|
*bytes = suffix;
|
|
|
|
|
|
Ok(Some(item))
|
|
|
|
|
|
|
|
|
// Split the prefix off. After this:
|
|
|
|
|
|
//
|
|
|
|
|
|
// | bytes (len 4) | suffix |
|
|
|
|
|
|
//
|
|
|
|
|
|
// NOTE: This method would be simpler if we could use split_to() instead
|
|
|
|
|
|
// here such that `bytes` contained the suffix. At the end, we would not
|
|
|
|
|
|
// have to replace `bytes` with `suffix`. However, that would require
|
|
|
|
|
|
// calling `prefix.unsplit(*bytes)`, and that does not work since
|
|
|
|
|
|
// `bytes` is only borrowed, and unsplit() takes its argument by value.
|
|
|
|
|
|
let mut suffix = bytes.split_off(U32_BYTE_LEN);
|
|
|
|
|
|
|
|
|
|
|
|
// unwrap() cannot panic because `bytes` is of the exact right length.
|
|
|
|
|
|
let array: [u8; U32_BYTE_LEN] = bytes.as_ref().try_into().unwrap();
|
|
|
|
|
|
let length = decode_u32(array) as usize;
|
|
|
|
|
|
|
|
|
|
|
|
if suffix.len() < length {
|
|
|
|
|
|
// Re-assemble `bytes` as it first was.
|
|
|
|
|
|
bytes.unsplit(suffix);
|
|
|
|
|
|
return Ok(None); // Not enough bytes yet.
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Split off the right amount of bytes from the buffer. After this:
|
|
|
|
|
|
//
|
|
|
|
|
|
// | bytes (len 4) | contents | suffix |
|
|
|
|
|
|
//
|
|
|
|
|
|
let mut contents = suffix.split_to(length);
|
|
|
|
|
|
|
|
|
|
|
|
// Attempt to decode the value.
|
|
|
|
|
|
let item = match ValueDecoder::new(&contents).decode() {
|
|
|
|
|
|
Ok(item) => item,
|
|
|
|
|
|
Err(error) => {
|
|
|
|
|
|
// Re-assemble `bytes` as it first was.
|
|
|
|
|
|
contents.unsplit(suffix);
|
|
|
|
|
|
bytes.unsplit(contents);
|
|
|
|
|
|
return Err(error);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the decoded bytes from the left of `bytes`.
|
|
|
|
|
|
*bytes = suffix;
|
|
|
|
|
|
Ok(Some(item))
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// An asynchronous sink for frames wrapping around a byte writer.
|
|
|
/// An asynchronous sink for frames wrapping around a byte writer.
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct FrameWriter<Frame: ?Sized, Writer> {
|
|
|
pub struct FrameWriter<Frame: ?Sized, Writer> {
|
|
|
encoder: FrameEncoder<Frame>,
|
|
|
|
|
|
writer: Writer,
|
|
|
|
|
|
|
|
|
encoder: FrameEncoder<Frame>,
|
|
|
|
|
|
writer: Writer,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<Frame, Writer> FrameWriter<Frame, Writer>
|
|
|
impl<Frame, Writer> FrameWriter<Frame, Writer>
|
|
|
where
|
|
|
where
|
|
|
Frame: ValueEncode + ?Sized,
|
|
|
|
|
|
Writer: AsyncWrite + Unpin,
|
|
|
|
|
|
|
|
|
Frame: ValueEncode + ?Sized,
|
|
|
|
|
|
Writer: AsyncWrite + Unpin,
|
|
|
{
|
|
|
{
|
|
|
pub fn new(writer: Writer) -> Self {
|
|
|
|
|
|
FrameWriter {
|
|
|
|
|
|
encoder: FrameEncoder::new(),
|
|
|
|
|
|
writer,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn new(writer: Writer) -> Self {
|
|
|
|
|
|
FrameWriter {
|
|
|
|
|
|
encoder: FrameEncoder::new(),
|
|
|
|
|
|
writer,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub async fn write(&mut self, frame: &Frame) -> io::Result<()> {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
self.encoder.encode_to(frame, &mut bytes)?;
|
|
|
|
|
|
self.writer.write_all(bytes.as_ref()).await
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub async fn write(&mut self, frame: &Frame) -> io::Result<()> {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
self.encoder.encode_to(frame, &mut bytes)?;
|
|
|
|
|
|
self.writer.write_all(bytes.as_ref()).await
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub async fn shutdown(&mut self) -> io::Result<()> {
|
|
|
|
|
|
self.writer.shutdown().await
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub async fn shutdown(&mut self) -> io::Result<()> {
|
|
|
|
|
|
self.writer.shutdown().await
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// An asynchronous stream of frames wrapping around a byte reader.
|
|
|
/// An asynchronous stream of frames wrapping around a byte reader.
|
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub struct FrameReader<Frame, Reader> {
|
|
|
pub struct FrameReader<Frame, Reader> {
|
|
|
decoder: FrameDecoder<Frame>,
|
|
|
|
|
|
reader: Reader,
|
|
|
|
|
|
read_buffer: BytesMut,
|
|
|
|
|
|
|
|
|
decoder: FrameDecoder<Frame>,
|
|
|
|
|
|
reader: Reader,
|
|
|
|
|
|
read_buffer: BytesMut,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<Frame, Reader> FrameReader<Frame, Reader>
|
|
|
impl<Frame, Reader> FrameReader<Frame, Reader>
|
|
|
where
|
|
|
where
|
|
|
Frame: ValueDecode,
|
|
|
|
|
|
Reader: AsyncRead + Unpin,
|
|
|
|
|
|
|
|
|
Frame: ValueDecode,
|
|
|
|
|
|
Reader: AsyncRead + Unpin,
|
|
|
{
|
|
|
{
|
|
|
pub fn new(reader: Reader) -> Self {
|
|
|
|
|
|
FrameReader {
|
|
|
|
|
|
decoder: FrameDecoder::new(),
|
|
|
|
|
|
reader,
|
|
|
|
|
|
read_buffer: BytesMut::new(),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
pub fn new(reader: Reader) -> Self {
|
|
|
|
|
|
FrameReader {
|
|
|
|
|
|
decoder: FrameDecoder::new(),
|
|
|
|
|
|
reader,
|
|
|
|
|
|
read_buffer: BytesMut::new(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Attempts to read the next frame from the underlying byte stream.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(Some(frame))` on success.
|
|
|
|
|
|
/// Returns `Ok(None)` if the stream has reached the end-of-file event.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns an error if reading from the stream returned an error or if an
|
|
|
|
|
|
/// invalid frame was received.
|
|
|
|
|
|
pub async fn read(&mut self) -> io::Result<Option<Frame>> {
|
|
|
|
|
|
loop {
|
|
|
|
|
|
if let Some(frame) = self.decoder.decode_from(&mut self.read_buffer)? {
|
|
|
|
|
|
return Ok(Some(frame));
|
|
|
|
|
|
}
|
|
|
|
|
|
if self.reader.read_buf(&mut self.read_buffer).await? == 0 {
|
|
|
|
|
|
return Ok(None);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Attempts to read the next frame from the underlying byte stream.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns `Ok(Some(frame))` on success.
|
|
|
|
|
|
/// Returns `Ok(None)` if the stream has reached the end-of-file event.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns an error if reading from the stream returned an error or if an
|
|
|
|
|
|
/// invalid frame was received.
|
|
|
|
|
|
pub async fn read(&mut self) -> io::Result<Option<Frame>> {
|
|
|
|
|
|
loop {
|
|
|
|
|
|
if let Some(frame) = self.decoder.decode_from(&mut self.read_buffer)? {
|
|
|
|
|
|
return Ok(Some(frame));
|
|
|
|
|
|
}
|
|
|
|
|
|
if self.reader.read_buf(&mut self.read_buffer).await? == 0 {
|
|
|
|
|
|
return Ok(None);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
#[cfg(test)]
|
|
|
mod tests {
|
|
|
mod tests {
|
|
|
use bytes::BytesMut;
|
|
|
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
|
|
|
|
|
|
|
|
use super::{FrameDecoder, FrameEncoder, FrameReader, FrameWriter};
|
|
|
|
|
|
|
|
|
|
|
|
// Test value: [1, 3, 3, 7] in little-endian.
|
|
|
|
|
|
const U32_1337: u32 = 1 + (3 << 8) + (3 << 16) + (7 << 24);
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_u32() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
FrameEncoder::new()
|
|
|
|
|
|
.encode_to(&U32_1337, &mut bytes)
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_appends() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
let mut encoder = FrameEncoder::new();
|
|
|
|
|
|
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
|
|
|
|
|
|
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
4, 0, 0, 0, // Repeated.
|
|
|
|
|
|
1, 3, 3, 7,
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_vec() {
|
|
|
|
|
|
let v: Vec<u32> = vec![1, 3, 3, 7];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
FrameEncoder::new().encode_to(&v, &mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
20, 0, 0, 0, // 5 32-bit integers = 20 bytes.
|
|
|
|
|
|
4, 0, 0, 0, // 4 elements in the vector.
|
|
|
|
|
|
1, 0, 0, 0, // Little-endian vector elements.
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
7, 0, 0, 0, //
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_not_enough_data_for_prefix() {
|
|
|
|
|
|
let initial_bytes = vec![
|
|
|
|
|
|
4, 0, 0, // Incomplete 32-bit length prefix.
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&initial_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
let value: Option<u32> = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, None);
|
|
|
|
|
|
assert_eq!(bytes, initial_bytes); // Untouched.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_not_enough_data_for_contents() {
|
|
|
|
|
|
let initial_bytes = vec![
|
|
|
|
|
|
4, 0, 0, 0, // Length 4.
|
|
|
|
|
|
1, 2, 3, // But there are only 3 bytes!
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&initial_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
let value: Option<u32> = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, None);
|
|
|
|
|
|
assert_eq!(bytes, initial_bytes); // Untouched.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_u32() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&[
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
4, 2, // Trailing bytes.
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, Some(U32_1337));
|
|
|
|
|
|
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_vec() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&[
|
|
|
|
|
|
20, 0, 0, 0, // 5 32-bit integers = 20 bytes.
|
|
|
|
|
|
4, 0, 0, 0, // 4 elements in the vector.
|
|
|
|
|
|
1, 0, 0, 0, // Little-endian vector elements.
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
7, 0, 0, 0, //
|
|
|
|
|
|
4, 2, // Trailing bytes.
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let expected_value: Vec<u32> = vec![1, 3, 3, 7];
|
|
|
|
|
|
assert_eq!(value, Some(expected_value));
|
|
|
|
|
|
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn roundtrip() {
|
|
|
|
|
|
let value: Vec<String> = vec![
|
|
|
|
|
|
"apples".to_string(), //
|
|
|
|
|
|
"bananas".to_string(), //
|
|
|
|
|
|
"oranges".to_string(), //
|
|
|
|
|
|
"and cheese!".to_string(), //
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut buffer = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
FrameEncoder::new().encode_to(&value, &mut buffer).unwrap();
|
|
|
|
|
|
let decoded = FrameDecoder::new().decode_from(&mut buffer).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(decoded, Some(value));
|
|
|
|
|
|
assert_eq!(buffer, vec![]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
|
async fn ping_pong() {
|
|
|
|
|
|
let listener = TcpListener::bind("localhost:0").await.unwrap();
|
|
|
|
|
|
let address = listener.local_addr().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let server_task = tokio::spawn(async move {
|
|
|
|
|
|
let (mut stream, _peer_address) = listener.accept().await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write("pong").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write("pong").await.unwrap();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let mut stream = TcpStream::connect(address).await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("pong".to_string()));
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("pong".to_string()));
|
|
|
|
|
|
|
|
|
|
|
|
server_task.await.unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
|
async fn very_large_message() {
|
|
|
|
|
|
let listener = TcpListener::bind("localhost:0").await.unwrap();
|
|
|
|
|
|
let address = listener.local_addr().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let server_task = tokio::spawn(async move {
|
|
|
|
|
|
let (mut stream, _peer_address) = listener.accept().await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write(&vec![0u32; 10 * 4096]).await.unwrap();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let mut stream = TcpStream::connect(address).await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some(vec![0u32; 10 * 4096]));
|
|
|
|
|
|
|
|
|
|
|
|
server_task.await.unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
use bytes::BytesMut;
|
|
|
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
|
|
|
|
|
|
|
|
use super::{FrameDecoder, FrameEncoder, FrameReader, FrameWriter};
|
|
|
|
|
|
|
|
|
|
|
|
// Test value: [1, 3, 3, 7] in little-endian.
|
|
|
|
|
|
const U32_1337: u32 = 1 + (3 << 8) + (3 << 16) + (7 << 24);
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_u32() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
FrameEncoder::new()
|
|
|
|
|
|
.encode_to(&U32_1337, &mut bytes)
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_appends() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
let mut encoder = FrameEncoder::new();
|
|
|
|
|
|
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
|
|
|
|
|
|
encoder.encode_to(&U32_1337, &mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
4, 0, 0, 0, // Repeated.
|
|
|
|
|
|
1, 3, 3, 7,
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn encode_vec() {
|
|
|
|
|
|
let v: Vec<u32> = vec![1, 3, 3, 7];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
FrameEncoder::new().encode_to(&v, &mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
|
bytes,
|
|
|
|
|
|
vec![
|
|
|
|
|
|
20, 0, 0, 0, // 5 32-bit integers = 20 bytes.
|
|
|
|
|
|
4, 0, 0, 0, // 4 elements in the vector.
|
|
|
|
|
|
1, 0, 0, 0, // Little-endian vector elements.
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
7, 0, 0, 0, //
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_not_enough_data_for_prefix() {
|
|
|
|
|
|
let initial_bytes = vec![
|
|
|
|
|
|
4, 0, 0, // Incomplete 32-bit length prefix.
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&initial_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
let value: Option<u32> =
|
|
|
|
|
|
FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, None);
|
|
|
|
|
|
assert_eq!(bytes, initial_bytes); // Untouched.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_not_enough_data_for_contents() {
|
|
|
|
|
|
let initial_bytes = vec![
|
|
|
|
|
|
4, 0, 0, 0, // Length 4.
|
|
|
|
|
|
1, 2, 3, // But there are only 3 bytes!
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&initial_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
let value: Option<u32> =
|
|
|
|
|
|
FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, None);
|
|
|
|
|
|
assert_eq!(bytes, initial_bytes); // Untouched.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_u32() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&[
|
|
|
|
|
|
4, 0, 0, 0, // 1 32-bit integer = 4 bytes.
|
|
|
|
|
|
1, 3, 3, 7, // Little-endian integer.
|
|
|
|
|
|
4, 2, // Trailing bytes.
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(value, Some(U32_1337));
|
|
|
|
|
|
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn decode_vec() {
|
|
|
|
|
|
let mut bytes = BytesMut::new();
|
|
|
|
|
|
bytes.extend_from_slice(&[
|
|
|
|
|
|
20, 0, 0, 0, // 5 32-bit integers = 20 bytes.
|
|
|
|
|
|
4, 0, 0, 0, // 4 elements in the vector.
|
|
|
|
|
|
1, 0, 0, 0, // Little-endian vector elements.
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
3, 0, 0, 0, //
|
|
|
|
|
|
7, 0, 0, 0, //
|
|
|
|
|
|
4, 2, // Trailing bytes.
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
let value = FrameDecoder::new().decode_from(&mut bytes).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let expected_value: Vec<u32> = vec![1, 3, 3, 7];
|
|
|
|
|
|
assert_eq!(value, Some(expected_value));
|
|
|
|
|
|
assert_eq!(bytes, vec![4, 2]); // Decoded bytes were split off.
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn roundtrip() {
|
|
|
|
|
|
let value: Vec<String> = vec![
|
|
|
|
|
|
"apples".to_string(), //
|
|
|
|
|
|
"bananas".to_string(), //
|
|
|
|
|
|
"oranges".to_string(), //
|
|
|
|
|
|
"and cheese!".to_string(), //
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let mut buffer = BytesMut::new();
|
|
|
|
|
|
|
|
|
|
|
|
FrameEncoder::new().encode_to(&value, &mut buffer).unwrap();
|
|
|
|
|
|
let decoded = FrameDecoder::new().decode_from(&mut buffer).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(decoded, Some(value));
|
|
|
|
|
|
assert_eq!(buffer, vec![]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
|
async fn ping_pong() {
|
|
|
|
|
|
let listener = TcpListener::bind("localhost:0").await.unwrap();
|
|
|
|
|
|
let address = listener.local_addr().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let server_task = tokio::spawn(async move {
|
|
|
|
|
|
let (mut stream, _peer_address) = listener.accept().await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write("pong").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write("pong").await.unwrap();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let mut stream = TcpStream::connect(address).await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("pong".to_string()));
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("pong".to_string()));
|
|
|
|
|
|
|
|
|
|
|
|
server_task.await.unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
|
async fn very_large_message() {
|
|
|
|
|
|
let listener = TcpListener::bind("localhost:0").await.unwrap();
|
|
|
|
|
|
let address = listener.local_addr().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let server_task = tokio::spawn(async move {
|
|
|
|
|
|
let (mut stream, _peer_address) = listener.accept().await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some("ping".to_string()));
|
|
|
|
|
|
writer.write(&vec![0u32; 10 * 4096]).await.unwrap();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let mut stream = TcpStream::connect(address).await.unwrap();
|
|
|
|
|
|
let (read_half, write_half) = stream.split();
|
|
|
|
|
|
let mut reader = FrameReader::new(read_half);
|
|
|
|
|
|
let mut writer = FrameWriter::new(write_half);
|
|
|
|
|
|
|
|
|
|
|
|
writer.write("ping").await.unwrap();
|
|
|
|
|
|
assert_eq!(reader.read().await.unwrap(), Some(vec![0u32; 10 * 4096]));
|
|
|
|
|
|
|
|
|
|
|
|
server_task.await.unwrap();
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|