task_local context over context objects
- interner impls logically separate from API in orchid-base (default host interner still in base for testing) - error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options - no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited - still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
@@ -1,33 +1,44 @@
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::hash::Hash;
|
||||
use std::io;
|
||||
use std::num::NonZero;
|
||||
use std::ops::{Range, RangeInclusive};
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_fn_stream::stream;
|
||||
use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, StreamExt};
|
||||
use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
use never::Never;
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::encode_enum;
|
||||
use crate::{decode_err, decode_err_for, encode_enum, spin_on};
|
||||
|
||||
pub trait Decode: 'static {
|
||||
pub trait Decode: 'static + Sized {
|
||||
/// Decode an instance from the beginning of the buffer. Return the decoded
|
||||
/// data and the remaining buffer.
|
||||
fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> impl Future<Output = Self> + '_;
|
||||
fn decode<R: AsyncRead + ?Sized>(
|
||||
read: Pin<&mut R>,
|
||||
) -> impl Future<Output = io::Result<Self>> + '_;
|
||||
fn decode_slice(slc: &mut &[u8]) -> Self {
|
||||
spin_on(Self::decode(Pin::new(slc) as Pin<&mut _>)).expect("Decode from slice cannot fail")
|
||||
}
|
||||
}
|
||||
pub trait Encode {
|
||||
/// Append an instance of the struct to the buffer
|
||||
fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> impl Future<Output = ()>;
|
||||
fn encode<W: AsyncWrite + ?Sized>(
|
||||
&self,
|
||||
write: Pin<&mut W>,
|
||||
) -> impl Future<Output = io::Result<()>>;
|
||||
fn encode_vec(&self, vec: &mut Vec<u8>) {
|
||||
spin_on(self.encode(Pin::new(vec) as Pin<&mut _>)).expect("Encode to vector cannot fail")
|
||||
}
|
||||
}
|
||||
pub trait Coding: Encode + Decode + Clone {
|
||||
fn get_decoder<T: 'static, F: Future<Output = T> + 'static>(
|
||||
map: impl Fn(Self) -> F + Clone + 'static,
|
||||
) -> impl AsyncFn(Pin<&mut dyn AsyncRead>) -> T {
|
||||
async move |r| map(Self::decode(r).await).await
|
||||
fn get_decoder<T: 'static>(
|
||||
map: impl AsyncFn(Self) -> T + Clone + 'static,
|
||||
) -> impl AsyncFn(Pin<&mut dyn AsyncRead>) -> io::Result<T> {
|
||||
async move |r| Ok(map(Self::decode(r).await?).await)
|
||||
}
|
||||
}
|
||||
impl<T: Encode + Decode + Clone> Coding for T {}
|
||||
@@ -35,15 +46,15 @@ impl<T: Encode + Decode + Clone> Coding for T {}
|
||||
macro_rules! num_impl {
|
||||
($number:ty) => {
|
||||
impl Decode for $number {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let mut bytes = [0u8; (<$number>::BITS / 8) as usize];
|
||||
read.read_exact(&mut bytes).await.unwrap();
|
||||
<$number>::from_be_bytes(bytes)
|
||||
read.read_exact(&mut bytes).await?;
|
||||
Ok(<$number>::from_be_bytes(bytes))
|
||||
}
|
||||
}
|
||||
impl Encode for $number {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
write.write_all(&self.to_be_bytes()).await.expect("Could not write number")
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
write.write_all(&self.to_be_bytes()).await
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -62,12 +73,12 @@ num_impl!(i8);
|
||||
macro_rules! nonzero_impl {
|
||||
($name:ty) => {
|
||||
impl Decode for NonZero<$name> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> Self {
|
||||
Self::new(<$name as Decode>::decode(read).await).unwrap()
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Self::new(<$name as Decode>::decode(read).await?).ok_or_else(decode_err)
|
||||
}
|
||||
}
|
||||
impl Encode for NonZero<$name> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
self.get().encode(write).await
|
||||
}
|
||||
}
|
||||
@@ -86,22 +97,22 @@ nonzero_impl!(i64);
|
||||
nonzero_impl!(i128);
|
||||
|
||||
impl<T: Encode + ?Sized> Encode for &T {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
(**self).encode(write).await
|
||||
}
|
||||
}
|
||||
macro_rules! float_impl {
|
||||
($t:ty, $size:expr) => {
|
||||
impl Decode for NotNan<$t> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let mut bytes = [0u8; $size];
|
||||
read.read_exact(&mut bytes).await.unwrap();
|
||||
NotNan::new(<$t>::from_be_bytes(bytes)).expect("Float was NaN")
|
||||
read.read_exact(&mut bytes).await?;
|
||||
NotNan::new(<$t>::from_be_bytes(bytes)).map_err(|_| decode_err())
|
||||
}
|
||||
}
|
||||
impl Encode for NotNan<$t> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
write.write_all(&self.as_ref().to_be_bytes()).await.expect("Could not write number")
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
write.write_all(&self.as_ref().to_be_bytes()).await
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -111,78 +122,77 @@ float_impl!(f64, 8);
|
||||
float_impl!(f32, 4);
|
||||
|
||||
impl Decode for String {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
let len: usize = u64::decode(read.as_mut()).await.try_into().unwrap();
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let len: usize = u64::decode(read.as_mut()).await?.try_into().map_err(decode_err_for)?;
|
||||
let mut data = vec![0u8; len];
|
||||
read.read_exact(&mut data).await.unwrap();
|
||||
std::str::from_utf8(&data).expect("String invalid UTF-8").to_owned()
|
||||
read.read_exact(&mut data).await?;
|
||||
Ok(std::str::from_utf8(&data).map_err(decode_err_for)?.to_owned())
|
||||
}
|
||||
}
|
||||
impl Encode for String {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await;
|
||||
write.write_all(self.as_bytes()).await.unwrap()
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
u64::try_from(self.len()).map_err(decode_err_for)?.encode(write.as_mut()).await?;
|
||||
write.write_all(self.as_bytes()).await
|
||||
}
|
||||
}
|
||||
impl Encode for str {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await;
|
||||
write.write_all(self.as_bytes()).await.unwrap()
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
u64::try_from(self.len()).map_err(decode_err_for)?.encode(write.as_mut()).await?;
|
||||
write.write_all(self.as_bytes()).await
|
||||
}
|
||||
}
|
||||
impl<T: Decode> Decode for Vec<T> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
let len = u64::decode(read.as_mut()).await;
|
||||
stream(async |mut cx| {
|
||||
for _ in 0..len {
|
||||
cx.emit(T::decode(read.as_mut()).await).await
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.await
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let len = u64::decode(read.as_mut()).await?;
|
||||
let mut values = Vec::with_capacity(len.try_into().map_err(decode_err_for)?);
|
||||
for _ in 0..len {
|
||||
values.push(T::decode(read.as_mut()).await?);
|
||||
}
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
impl<T: Encode> Encode for Vec<T> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
self.as_slice().encode(write).await
|
||||
}
|
||||
}
|
||||
impl<T: Encode> Encode for [T] {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await;
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await?;
|
||||
for t in self.iter() {
|
||||
t.encode(write.as_mut()).await
|
||||
t.encode(write.as_mut()).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<T: Decode> Decode for Option<T> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
match u8::decode(read.as_mut()).await {
|
||||
0 => None,
|
||||
1 => Some(T::decode(read).await),
|
||||
x => panic!("{x} is not a valid option value"),
|
||||
}
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Ok(match bool::decode(read.as_mut()).await? {
|
||||
false => None,
|
||||
true => Some(T::decode(read).await?),
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<T: Encode> Encode for Option<T> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
let t = if let Some(t) = self { t } else { return 0u8.encode(write.as_mut()).await };
|
||||
1u8.encode(write.as_mut()).await;
|
||||
t.encode(write).await;
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
self.is_some().encode(write.as_mut()).await?;
|
||||
if let Some(t) = self {
|
||||
t.encode(write).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<T: Decode, E: Decode> Decode for Result<T, E> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
match u8::decode(read.as_mut()).await {
|
||||
0 => Self::Ok(T::decode(read).await),
|
||||
1 => Self::Err(E::decode(read).await),
|
||||
x => panic!("Invalid Result tag {x}"),
|
||||
}
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Ok(match bool::decode(read.as_mut()).await? {
|
||||
false => Self::Ok(T::decode(read).await?),
|
||||
true => Self::Err(E::decode(read).await?),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode, E: Encode> Encode for Result<T, E> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
match self {
|
||||
Ok(t) => encode_enum(write, 0, |w| t.encode(w)).await,
|
||||
Err(e) => encode_enum(write, 1, |w| e.encode(w)).await,
|
||||
@@ -190,36 +200,37 @@ impl<T: Encode, E: Encode> Encode for Result<T, E> {
|
||||
}
|
||||
}
|
||||
impl<K: Decode + Eq + Hash, V: Decode> Decode for HashMap<K, V> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
let len = u64::decode(read.as_mut()).await;
|
||||
stream(async |mut cx| {
|
||||
for _ in 0..len {
|
||||
cx.emit(<(K, V)>::decode(read.as_mut()).await).await
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.await
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let len = u64::decode(read.as_mut()).await?;
|
||||
let mut map = HashMap::with_capacity(len.try_into().map_err(decode_err_for)?);
|
||||
for _ in 0..len {
|
||||
map.insert(K::decode(read.as_mut()).await?, V::decode(read.as_mut()).await?);
|
||||
}
|
||||
Ok(map)
|
||||
}
|
||||
}
|
||||
impl<K: Encode + Eq + Hash, V: Encode> Encode for HashMap<K, V> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await;
|
||||
for pair in self.iter() {
|
||||
pair.encode(write.as_mut()).await
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
u64::try_from(self.len()).unwrap().encode(write.as_mut()).await?;
|
||||
for (key, value) in self.iter() {
|
||||
key.encode(write.as_mut()).await?;
|
||||
value.encode(write.as_mut()).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
macro_rules! tuple {
|
||||
(($($t:ident)*) ($($T:ident)*)) => {
|
||||
impl<$($T: Decode),*> Decode for ($($T,)*) {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
($($T::decode(read.as_mut()).await,)*)
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Ok(($($T::decode(read.as_mut()).await?,)*))
|
||||
}
|
||||
}
|
||||
impl<$($T: Encode),*> Encode for ($($T,)*) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
let ($($t,)*) = self;
|
||||
$( $t.encode(write.as_mut()).await; )*
|
||||
$( $t.encode(write.as_mut()).await?; )*
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -243,63 +254,67 @@ tuple!((t u v x y z a b c d e f g h i) (T U V X Y Z A B C D E F G H I));
|
||||
tuple!((t u v x y z a b c d e f g h i j) (T U V X Y Z A B C D E F G H I J)); // 16
|
||||
|
||||
impl Decode for () {
|
||||
async fn decode<R: AsyncRead + ?Sized>(_: Pin<&mut R>) -> Self {}
|
||||
async fn decode<R: AsyncRead + ?Sized>(_: Pin<&mut R>) -> io::Result<Self> { Ok(()) }
|
||||
}
|
||||
impl Encode for () {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, _: Pin<&mut W>) {}
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, _: Pin<&mut W>) -> io::Result<()> { Ok(()) }
|
||||
}
|
||||
impl Decode for Never {
|
||||
async fn decode<R: AsyncRead + ?Sized>(_: Pin<&mut R>) -> Self {
|
||||
async fn decode<R: AsyncRead + ?Sized>(_: Pin<&mut R>) -> io::Result<Self> {
|
||||
unreachable!("A value of Never cannot exist so it can't have been serialized");
|
||||
}
|
||||
}
|
||||
impl Encode for Never {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, _: Pin<&mut W>) { match *self {} }
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, _: Pin<&mut W>) -> io::Result<()> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
impl Decode for bool {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let mut buf = [0];
|
||||
read.read_exact(&mut buf).await.unwrap();
|
||||
buf[0] != 0
|
||||
read.read_exact(&mut buf).await?;
|
||||
Ok(buf[0] != 0)
|
||||
}
|
||||
}
|
||||
impl Encode for bool {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
write.write_all(&[if *self { 0xffu8 } else { 0u8 }]).await.unwrap()
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
write.write_all(&[if *self { 0xffu8 } else { 0u8 }]).await
|
||||
}
|
||||
}
|
||||
impl<T: Decode, const N: usize> Decode for [T; N] {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
let v = stream(async |mut cx| {
|
||||
for _ in 0..N {
|
||||
cx.emit(T::decode(read.as_mut()).await).await
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
v.try_into().unwrap_or_else(|_| unreachable!("The length of this stream is statically known"))
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
let mut v = Vec::with_capacity(N);
|
||||
for _ in 0..N {
|
||||
v.push(T::decode(read.as_mut()).await?);
|
||||
}
|
||||
match v.try_into() {
|
||||
Err(_) => unreachable!("The length of this stream is statically known"),
|
||||
Ok(arr) => Ok(arr),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Encode, const N: usize> Encode for [T; N] {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
for t in self.iter() {
|
||||
t.encode(write.as_mut()).await
|
||||
t.encode(write.as_mut()).await?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! two_end_range {
|
||||
($this:ident, $name:tt, $op:tt, $start:expr, $end:expr) => {
|
||||
impl<T: Decode> Decode for $name<T> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> Self {
|
||||
T::decode(read.as_mut()).await $op T::decode(read).await
|
||||
async fn decode<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Ok(T::decode(read.as_mut()).await? $op T::decode(read).await?)
|
||||
}
|
||||
}
|
||||
impl<T: Encode> Encode for $name<T> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, mut write: Pin<&mut W>) -> io::Result<()> {
|
||||
let $this = self;
|
||||
($start).encode(write.as_mut()).await;
|
||||
($end).encode(write).await;
|
||||
($start).encode(write.as_mut()).await?;
|
||||
($end).encode(write).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,12 +326,12 @@ two_end_range!(x, RangeInclusive, ..=, x.start(), x.end());
|
||||
macro_rules! smart_ptr {
|
||||
($name:tt) => {
|
||||
impl<T: Decode> Decode for $name<T> {
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> Self {
|
||||
$name::new(T::decode(read).await)
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> io::Result<Self> {
|
||||
Ok($name::new(T::decode(read).await?))
|
||||
}
|
||||
}
|
||||
impl<T: Encode> Encode for $name<T> {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
(**self).encode(write).await
|
||||
}
|
||||
}
|
||||
@@ -328,12 +343,12 @@ smart_ptr!(Rc);
|
||||
smart_ptr!(Box);
|
||||
|
||||
impl Decode for char {
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> Self {
|
||||
char::from_u32(u32::decode(read).await).unwrap()
|
||||
async fn decode<R: AsyncRead + ?Sized>(read: Pin<&mut R>) -> io::Result<Self> {
|
||||
char::from_u32(u32::decode(read).await?).ok_or_else(decode_err)
|
||||
}
|
||||
}
|
||||
impl Encode for char {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) {
|
||||
async fn encode<W: AsyncWrite + ?Sized>(&self, write: Pin<&mut W>) -> io::Result<()> {
|
||||
(*self as u32).encode(write).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::pin::{Pin, pin};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::task::{Context, Poll, Wake};
|
||||
|
||||
use futures::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
use futures::{AsyncRead, AsyncReadExt, AsyncWrite};
|
||||
use itertools::{Chunk, Itertools};
|
||||
|
||||
use crate::Encode;
|
||||
|
||||
pub async fn encode_enum<'a, W: AsyncWrite + ?Sized, F: Future<Output = ()>>(
|
||||
pub async fn encode_enum<'a, W: AsyncWrite + ?Sized>(
|
||||
mut write: Pin<&'a mut W>,
|
||||
id: u8,
|
||||
f: impl FnOnce(Pin<&'a mut W>) -> F,
|
||||
) {
|
||||
id.encode(write.as_mut()).await;
|
||||
f: impl AsyncFnOnce(Pin<&'a mut W>) -> io::Result<()>,
|
||||
) -> io::Result<()> {
|
||||
id.encode(write.as_mut()).await?;
|
||||
f(write).await
|
||||
}
|
||||
|
||||
pub async fn write_exact<W: AsyncWrite + ?Sized>(mut write: Pin<&mut W>, bytes: &'static [u8]) {
|
||||
write.write_all(bytes).await.expect("Failed to write exact bytes")
|
||||
}
|
||||
|
||||
pub fn print_bytes(b: &[u8]) -> String {
|
||||
(b.iter().map(|b| format!("{b:02x}")))
|
||||
.chunks(4)
|
||||
@@ -27,16 +27,52 @@ pub fn print_bytes(b: &[u8]) -> String {
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
pub async fn read_exact<R: AsyncRead + ?Sized>(mut read: Pin<&mut R>, bytes: &'static [u8]) {
|
||||
pub async fn read_exact<R: AsyncRead + ?Sized>(
|
||||
mut read: Pin<&mut R>,
|
||||
bytes: &'static [u8],
|
||||
) -> io::Result<()> {
|
||||
let mut data = vec![0u8; bytes.len()];
|
||||
read.read_exact(&mut data).await.expect("Failed to read bytes");
|
||||
if data != bytes {
|
||||
panic!("Wrong bytes!\nExpected: {}\nFound: {}", print_bytes(bytes), print_bytes(&data));
|
||||
read.read_exact(&mut data).await?;
|
||||
if data == bytes {
|
||||
Ok(())
|
||||
} else {
|
||||
let msg =
|
||||
format!("Wrong bytes!\nExpected: {}\nFound: {}", print_bytes(bytes), print_bytes(&data));
|
||||
Err(io::Error::new(io::ErrorKind::InvalidData, msg))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn enc_vec(enc: &impl Encode) -> Vec<u8> {
|
||||
pub fn enc_vec(enc: &impl Encode) -> Vec<u8> {
|
||||
let mut vec = Vec::new();
|
||||
enc.encode(Pin::new(&mut vec)).await;
|
||||
enc.encode_vec(&mut vec);
|
||||
vec
|
||||
}
|
||||
|
||||
/// Raises a bool flag when called
|
||||
struct FlagWaker(AtomicBool);
|
||||
impl Wake for FlagWaker {
|
||||
fn wake(self: Arc<Self>) { self.0.store(true, Ordering::Relaxed) }
|
||||
}
|
||||
|
||||
pub fn spin_on<F: Future>(fut: F) -> F::Output {
|
||||
let flag = AtomicBool::new(false);
|
||||
let flag_waker = Arc::new(FlagWaker(flag));
|
||||
let mut future = pin!(fut);
|
||||
loop {
|
||||
let waker = flag_waker.clone().into();
|
||||
let mut ctx = Context::from_waker(&waker);
|
||||
match future.as_mut().poll(&mut ctx) {
|
||||
// ideally the future should return synchronously
|
||||
Poll::Ready(res) => break res,
|
||||
// poorly written futures may yield and immediately wake
|
||||
Poll::Pending if flag_waker.0.load(Ordering::Relaxed) => (),
|
||||
// there is no external event to wait for, this has to be a deadlock
|
||||
Poll::Pending => panic!("Future inside spin_on cannot block"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_err() -> io::Error { io::Error::new(io::ErrorKind::InvalidData, "Unexpected zero") }
|
||||
pub fn decode_err_for(e: impl Error) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::InvalidData, e.to_string())
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ pub trait Request: fmt::Debug + Sized + 'static {
|
||||
type Response: fmt::Debug + Coding + 'static;
|
||||
}
|
||||
|
||||
pub async fn respond<R: Request>(_: &R, rep: R::Response) -> Vec<u8> { enc_vec(&rep).await }
|
||||
pub fn respond<R: Request>(_: &R, rep: R::Response) -> Vec<u8> { enc_vec(&rep) }
|
||||
|
||||
pub trait Channel: 'static {
|
||||
type Req: Coding + Sized + 'static;
|
||||
|
||||
Reference in New Issue
Block a user