| 1 | use crate::io::AsyncWrite; |
| 2 | |
| 3 | use bytes::BufMut; |
| 4 | use pin_project_lite::pin_project; |
| 5 | use std::future::Future; |
| 6 | use std::io; |
| 7 | use std::marker::PhantomPinned; |
| 8 | use std::pin::Pin; |
| 9 | use std::task::{Context, Poll}; |
| 10 | |
| 11 | macro_rules! writer { |
| 12 | ($name:ident, $ty:ty, $writer:ident) => { |
| 13 | writer!($name, $ty, $writer, std::mem::size_of::<$ty>()); |
| 14 | }; |
| 15 | ($name:ident, $ty:ty, $writer:ident, $bytes:expr) => { |
| 16 | pin_project! { |
| 17 | #[doc(hidden)] |
| 18 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
| 19 | pub struct $name<W> { |
| 20 | #[pin] |
| 21 | dst: W, |
| 22 | buf: [u8; $bytes], |
| 23 | written: u8, |
| 24 | // Make this future `!Unpin` for compatibility with async trait methods. |
| 25 | #[pin] |
| 26 | _pin: PhantomPinned, |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | impl<W> $name<W> { |
| 31 | pub(crate) fn new(w: W, value: $ty) -> Self { |
| 32 | let mut writer = Self { |
| 33 | buf: [0; $bytes], |
| 34 | written: 0, |
| 35 | dst: w, |
| 36 | _pin: PhantomPinned, |
| 37 | }; |
| 38 | BufMut::$writer(&mut &mut writer.buf[..], value); |
| 39 | writer |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | impl<W> Future for $name<W> |
| 44 | where |
| 45 | W: AsyncWrite, |
| 46 | { |
| 47 | type Output = io::Result<()>; |
| 48 | |
| 49 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 50 | let mut me = self.project(); |
| 51 | |
| 52 | if *me.written == $bytes as u8 { |
| 53 | return Poll::Ready(Ok(())); |
| 54 | } |
| 55 | |
| 56 | while *me.written < $bytes as u8 { |
| 57 | *me.written += match me |
| 58 | .dst |
| 59 | .as_mut() |
| 60 | .poll_write(cx, &me.buf[*me.written as usize..]) |
| 61 | { |
| 62 | Poll::Pending => return Poll::Pending, |
| 63 | Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())), |
| 64 | Poll::Ready(Ok(0)) => { |
| 65 | return Poll::Ready(Err(io::ErrorKind::WriteZero.into())); |
| 66 | } |
| 67 | Poll::Ready(Ok(n)) => n as u8, |
| 68 | }; |
| 69 | } |
| 70 | Poll::Ready(Ok(())) |
| 71 | } |
| 72 | } |
| 73 | }; |
| 74 | } |
| 75 | |
| 76 | macro_rules! writer8 { |
| 77 | ($name:ident, $ty:ty) => { |
| 78 | pin_project! { |
| 79 | #[doc(hidden)] |
| 80 | #[must_use = "futures do nothing unless you `.await` or poll them" ] |
| 81 | pub struct $name<W> { |
| 82 | #[pin] |
| 83 | dst: W, |
| 84 | byte: $ty, |
| 85 | // Make this future `!Unpin` for compatibility with async trait methods. |
| 86 | #[pin] |
| 87 | _pin: PhantomPinned, |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | impl<W> $name<W> { |
| 92 | pub(crate) fn new(dst: W, byte: $ty) -> Self { |
| 93 | Self { |
| 94 | dst, |
| 95 | byte, |
| 96 | _pin: PhantomPinned, |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | impl<W> Future for $name<W> |
| 102 | where |
| 103 | W: AsyncWrite, |
| 104 | { |
| 105 | type Output = io::Result<()>; |
| 106 | |
| 107 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
| 108 | let me = self.project(); |
| 109 | |
| 110 | let buf = [*me.byte as u8]; |
| 111 | |
| 112 | match me.dst.poll_write(cx, &buf[..]) { |
| 113 | Poll::Pending => Poll::Pending, |
| 114 | Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), |
| 115 | Poll::Ready(Ok(0)) => Poll::Ready(Err(io::ErrorKind::WriteZero.into())), |
| 116 | Poll::Ready(Ok(1)) => Poll::Ready(Ok(())), |
| 117 | Poll::Ready(Ok(_)) => unreachable!(), |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | }; |
| 122 | } |
| 123 | |
| 124 | writer8!(WriteU8, u8); |
| 125 | writer8!(WriteI8, i8); |
| 126 | |
| 127 | writer!(WriteU16, u16, put_u16); |
| 128 | writer!(WriteU32, u32, put_u32); |
| 129 | writer!(WriteU64, u64, put_u64); |
| 130 | writer!(WriteU128, u128, put_u128); |
| 131 | |
| 132 | writer!(WriteI16, i16, put_i16); |
| 133 | writer!(WriteI32, i32, put_i32); |
| 134 | writer!(WriteI64, i64, put_i64); |
| 135 | writer!(WriteI128, i128, put_i128); |
| 136 | |
| 137 | writer!(WriteF32, f32, put_f32); |
| 138 | writer!(WriteF64, f64, put_f64); |
| 139 | |
| 140 | writer!(WriteU16Le, u16, put_u16_le); |
| 141 | writer!(WriteU32Le, u32, put_u32_le); |
| 142 | writer!(WriteU64Le, u64, put_u64_le); |
| 143 | writer!(WriteU128Le, u128, put_u128_le); |
| 144 | |
| 145 | writer!(WriteI16Le, i16, put_i16_le); |
| 146 | writer!(WriteI32Le, i32, put_i32_le); |
| 147 | writer!(WriteI64Le, i64, put_i64_le); |
| 148 | writer!(WriteI128Le, i128, put_i128_le); |
| 149 | |
| 150 | writer!(WriteF32Le, f32, put_f32_le); |
| 151 | writer!(WriteF64Le, f64, put_f64_le); |
| 152 | |