#[cfg(any(feature = "rpc", feature = "varint-util"))]
mod varint_util {
use std::{
future::Future,
io::{self, Error},
};
use serde::{Serialize, de::DeserializeOwned};
use smallvec::SmallVec;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub async fn read_varint_u64<R>(reader: &mut R) -> io::Result<Option<u64>>
where
R: AsyncRead + Unpin,
{
let mut result: u64 = 0;
let mut shift: u32 = 0;
loop {
if shift >= 64 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Varint is too large for u64",
));
}
let res = reader.read_u8().await;
if shift == 0
&& let Err(cause) = res
{
if cause.kind() == io::ErrorKind::UnexpectedEof {
return Ok(None);
} else {
return Err(cause);
}
}
let byte = res?;
let value = (byte & 0x7F) as u64;
if shift == 63 && value > 1 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Varint is too large for u64",
));
}
result |= value << shift;
if byte & 0x80 == 0 {
break;
}
shift += 7;
}
Ok(Some(result))
}
pub fn write_varint_u64_sync<W: std::io::Write>(
writer: &mut W,
value: u64,
) -> std::io::Result<usize> {
if value == 0 {
writer.write_all(&[0])?;
return Ok(1);
}
let mut bytes_written = 0;
let mut remaining = value;
while remaining > 0 {
let mut byte = (remaining & 0x7F) as u8;
remaining >>= 7;
if remaining > 0 {
byte |= 0x80;
}
writer.write_all(&[byte])?;
bytes_written += 1;
}
Ok(bytes_written)
}
pub fn write_length_prefixed<T: Serialize>(
mut write: impl std::io::Write,
value: T,
) -> io::Result<()> {
let size = postcard::experimental::serialized_size(&value)
.map_err(|e| Error::new(io::ErrorKind::InvalidData, e))? as u64;
write_varint_u64_sync(&mut write, size)?;
postcard::to_io(&value, &mut write)
.map_err(|e| Error::new(io::ErrorKind::InvalidData, e))?;
Ok(())
}
pub trait AsyncReadVarintExt: AsyncRead + Unpin {
fn read_varint_u64(&mut self) -> impl Future<Output = io::Result<Option<u64>>>;
fn read_length_prefixed<T: DeserializeOwned>(
&mut self,
max_size: usize,
) -> impl Future<Output = io::Result<T>>;
}
impl<T: AsyncRead + Unpin> AsyncReadVarintExt for T {
fn read_varint_u64(&mut self) -> impl Future<Output = io::Result<Option<u64>>> {
read_varint_u64(self)
}
async fn read_length_prefixed<I: DeserializeOwned>(
&mut self,
max_size: usize,
) -> io::Result<I> {
let size = match self.read_varint_u64().await? {
Some(size) => size,
None => return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "EOF reached")),
};
if size > max_size as u64 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Length-prefixed value too large",
));
}
let mut buf = vec![0; size as usize];
self.read_exact(&mut buf).await?;
postcard::from_bytes(&buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
}
}
pub trait WriteVarintExt: std::io::Write {
fn write_varint_u64(&mut self, value: u64) -> io::Result<usize>;
fn write_length_prefixed<T: Serialize>(&mut self, value: T) -> io::Result<()>;
}
impl<T: std::io::Write> WriteVarintExt for T {
fn write_varint_u64(&mut self, value: u64) -> io::Result<usize> {
write_varint_u64_sync(self, value)
}
fn write_length_prefixed<V: Serialize>(&mut self, value: V) -> io::Result<()> {
write_length_prefixed(self, value)
}
}
pub trait AsyncWriteVarintExt: AsyncWrite + Unpin {
fn write_varint_u64(&mut self, value: u64) -> impl Future<Output = io::Result<usize>>;
fn write_length_prefixed<T: Serialize>(
&mut self,
value: T,
) -> impl Future<Output = io::Result<usize>>;
}
impl<T: AsyncWrite + Unpin> AsyncWriteVarintExt for T {
async fn write_varint_u64(&mut self, value: u64) -> io::Result<usize> {
let mut buf: SmallVec<[u8; 10]> = Default::default();
write_varint_u64_sync(&mut buf, value).unwrap();
self.write_all(&buf[..]).await?;
Ok(buf.len())
}
async fn write_length_prefixed<V: Serialize>(&mut self, value: V) -> io::Result<usize> {
let mut buf = Vec::new();
write_length_prefixed(&mut buf, value)?;
let size = buf.len();
self.write_all(&buf).await?;
Ok(size)
}
}
}
#[cfg(any(feature = "rpc", feature = "varint-util"))]
pub use varint_util::{AsyncReadVarintExt, AsyncWriteVarintExt, WriteVarintExt};
mod fuse_wrapper {
use std::{
future::Future,
pin::Pin,
result::Result,
task::{Context, Poll},
};
pub struct FusedOneshotReceiver<T>(pub tokio::sync::oneshot::Receiver<T>);
impl<T> Future for FusedOneshotReceiver<T> {
type Output = Result<T, tokio::sync::oneshot::error::RecvError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0.is_terminated() {
Poll::Pending
} else {
Future::poll(Pin::new(&mut self.0), cx)
}
}
}
}
pub(crate) use fuse_wrapper::FusedOneshotReceiver;
#[cfg(feature = "rpc")]
mod now_or_never {
use std::{
future::Future,
pin::Pin,
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
macro_rules! pin_mut {
($($x:ident),* $(,)?) => {
$(
let mut $x = $x;
#[allow(unused_mut)]
let mut $x = unsafe { Pin::new_unchecked(&mut $x) };
)*
}
}
fn noop_waker() -> Waker {
fn noop(_: *const ()) {}
fn clone(_: *const ()) -> RawWaker {
let vtable = &RawWakerVTable::new(clone, noop, noop, noop);
RawWaker::new(std::ptr::null(), vtable)
}
unsafe { Waker::from_raw(clone(std::ptr::null())) }
}
pub(crate) fn now_or_never<F: Future>(future: F) -> Option<F::Output> {
let waker = noop_waker();
let mut cx = Context::from_waker(&waker);
pin_mut!(future);
match future.poll(&mut cx) {
Poll::Ready(x) => Some(x),
Poll::Pending => None,
}
}
}
#[cfg(feature = "rpc")]
pub(crate) use now_or_never::now_or_never;
#[cfg(all(test, any(feature = "rpc", feature = "varint-util")))]
mod tests {
use super::{AsyncReadVarintExt, WriteVarintExt};
#[tokio::test]
async fn varint_rejects_values_larger_than_u64() {
let mut buf = Vec::new();
buf.write_varint_u64(u64::MAX).unwrap();
assert_eq!(buf.len(), 10);
assert_eq!(
buf.as_slice().read_varint_u64().await.unwrap(),
Some(u64::MAX)
);
let mut too_large = [0x80; 10];
too_large[9] = 0x02;
let err = too_large.as_slice().read_varint_u64().await.unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
let err = [0xff; 11].as_slice().read_varint_u64().await.unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::InvalidData);
}
}