mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-25 12:00:35 +00:00
io: read/write big-endian numbers (#1863)
Provide convenience methods for encoding and decoding big-endian numbers on top of asynchronous I/O streams. Only primitive types are provided (24 and 48 bit numbers are omitted). In general, using these methods won't be the fastest way to do encoding/decoding with asynchronous byte streams, but they help to get simple things working fast.
This commit is contained in:
parent
8ce408492a
commit
1ea6733568
@ -1,12 +1,31 @@
|
||||
use crate::io::util::chain::{chain, Chain};
|
||||
use crate::io::util::read::{read, Read};
|
||||
use crate::io::util::read_exact::{read_exact, ReadExact};
|
||||
use crate::io::util::read_int::{ReadU8, ReadU16, ReadU32, ReadU64, ReadU128};
|
||||
use crate::io::util::read_int::{ReadI8, ReadI16, ReadI32, ReadI64, ReadI128};
|
||||
use crate::io::util::read_to_end::{read_to_end, ReadToEnd};
|
||||
use crate::io::util::read_to_string::{read_to_string, ReadToString};
|
||||
use crate::io::util::take::{take, Take};
|
||||
use crate::io::AsyncRead;
|
||||
|
||||
cfg_io_util! {
|
||||
/// Define numeric reader
|
||||
macro_rules! read_impl {
|
||||
(
|
||||
$(
|
||||
$(#[$outer:meta])*
|
||||
fn $name:ident(&mut self) -> $($fut:ident)*;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$outer])*
|
||||
fn $name<'a>(&'a mut self) -> $($fut)*<&'a mut Self> where Self: Unpin {
|
||||
$($fut)*::new(self)
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// Read bytes from a source.
|
||||
///
|
||||
/// Implemented as an extention trait, adding utility methods to all
|
||||
@ -199,6 +218,391 @@ cfg_io_util! {
|
||||
read_exact(self, buf)
|
||||
}
|
||||
|
||||
read_impl! {
|
||||
/// Reads an unsigned 8 bit integer from the underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_u8(&mut self) -> io::Result<u8>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 8 bit integers from an `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![2, 5]);
|
||||
///
|
||||
/// assert_eq!(2, reader.read_u8().await?);
|
||||
/// assert_eq!(5, reader.read_u8().await?);
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_u8(&mut self) -> ReadU8;
|
||||
|
||||
/// Reads a signed 8 bit integer from the underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_i8(&mut self) -> io::Result<i8>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 8 bit integers from an `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![0x02, 0xfb]);
|
||||
///
|
||||
/// assert_eq!(2, reader.read_i8().await?);
|
||||
/// assert_eq!(-5, reader.read_i8().await?);
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_i8(&mut self) -> ReadI8;
|
||||
|
||||
/// Reads an unsigned 16-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_u16(&mut self) -> io::Result<u16>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 16 bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![2, 5, 3, 0]);
|
||||
///
|
||||
/// assert_eq!(517, reader.read_u16().await?);
|
||||
/// assert_eq!(768, reader.read_u16().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_u16(&mut self) -> ReadU16;
|
||||
|
||||
/// Reads a signed 16-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_i16(&mut self) -> io::Result<i16>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read signed 16 bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
|
||||
///
|
||||
/// assert_eq!(193, reader.read_i16().await?);
|
||||
/// assert_eq!(-132, reader.read_i16().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_i16(&mut self) -> ReadI16;
|
||||
|
||||
/// Reads an unsigned 32-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_u32(&mut self) -> io::Result<u32>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 32-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
|
||||
///
|
||||
/// assert_eq!(267, reader.read_u32().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_u32(&mut self) -> ReadU32;
|
||||
|
||||
/// Reads a signed 32-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_i32(&mut self) -> io::Result<i32>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read signed 32-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
|
||||
///
|
||||
/// assert_eq!(-34253, reader.read_i32().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_i32(&mut self) -> ReadI32;
|
||||
|
||||
/// Reads an unsigned 64-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_u64(&mut self) -> io::Result<u64>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 64-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![
|
||||
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(918733457491587, reader.read_u64().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_u64(&mut self) -> ReadU64;
|
||||
|
||||
/// Reads an signed 64-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_i64(&mut self) -> io::Result<i64>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read signed 64-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
|
||||
///
|
||||
/// assert_eq!(i64::min_value(), reader.read_i64().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_i64(&mut self) -> ReadI64;
|
||||
|
||||
/// Reads an unsigned 128-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_u128(&mut self) -> io::Result<u128>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read unsigned 128-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![
|
||||
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
|
||||
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(16947640962301618749969007319746179, reader.read_u128().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_u128(&mut self) -> ReadU128;
|
||||
|
||||
/// Reads an signed 128-bit integer in big-endian order from the
|
||||
/// underlying reader.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn read_i128(&mut self) -> io::Result<i128>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered reader to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncReadExt::read_exact`].
|
||||
///
|
||||
/// [`AsyncReadExt::read_exact`]: AsyncReadExt::read_exact
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Read signed 128-bit big-endian integers from a `AsyncRead`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncReadExt};
|
||||
///
|
||||
/// use std::io::Cursor;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut reader = Cursor::new(vec![
|
||||
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
|
||||
/// 0, 0, 0, 0, 0, 0, 0, 0
|
||||
/// ]);
|
||||
///
|
||||
/// assert_eq!(i128::min_value(), reader.read_i128().await?);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn read_i128(&mut self) -> ReadI128;
|
||||
}
|
||||
|
||||
/// Read all bytes until EOF in this source, placing them into `buf`.
|
||||
///
|
||||
/// Equivalent to:
|
||||
|
@ -2,9 +2,28 @@ use crate::io::util::flush::{flush, Flush};
|
||||
use crate::io::util::shutdown::{shutdown, Shutdown};
|
||||
use crate::io::util::write::{write, Write};
|
||||
use crate::io::util::write_all::{write_all, WriteAll};
|
||||
use crate::io::util::write_int::{WriteU8, WriteU16, WriteU32, WriteU64, WriteU128};
|
||||
use crate::io::util::write_int::{WriteI8, WriteI16, WriteI32, WriteI64, WriteI128};
|
||||
use crate::io::AsyncWrite;
|
||||
|
||||
cfg_io_util! {
|
||||
/// Define numeric writer
|
||||
macro_rules! write_impl {
|
||||
(
|
||||
$(
|
||||
$(#[$outer:meta])*
|
||||
fn $name:ident(&mut self, n: $ty:ty) -> $($fut:ident)*;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$outer])*
|
||||
fn $name<'a>(&'a mut self, n: $ty) -> $($fut)*<&'a mut Self> where Self: Unpin {
|
||||
$($fut)*::new(self, n)
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
/// Write bytes to a sink.
|
||||
///
|
||||
/// Implemented as an extention trait, adding utility methods to all
|
||||
@ -129,6 +148,390 @@ cfg_io_util! {
|
||||
write_all(self, src)
|
||||
}
|
||||
|
||||
write_impl! {
|
||||
/// Writes an unsigned 8-bit integer to the underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_u8(&mut self, n: u8) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 8 bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u8(2).await?;
|
||||
/// writer.write_u8(5).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x02\x05");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_u8(&mut self, n: u8) -> WriteU8;
|
||||
|
||||
/// Writes an unsigned 8-bit integer to the underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_i8(&mut self, n: i8) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 8 bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u8(2).await?;
|
||||
/// writer.write_u8(5).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x02\x05");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_i8(&mut self, n: i8) -> WriteI8;
|
||||
|
||||
/// Writes an unsigned 16-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_u16(&mut self, n: u16) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 16-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u16(517).await?;
|
||||
/// writer.write_u16(768).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x02\x05\x03\x00");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_u16(&mut self, n: u16) -> WriteU16;
|
||||
|
||||
/// Writes a signed 16-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_i16(&mut self, n: i16) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write signed 16-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_i16(193).await?;
|
||||
/// writer.write_i16(-132).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x00\xc1\xff\x7c");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_i16(&mut self, n: i16) -> WriteI16;
|
||||
|
||||
/// Writes an unsigned 32-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_u32(&mut self, n: u32) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 32-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u32(267).await?;
|
||||
/// writer.write_u32(1205419366).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_u32(&mut self, n: u32) -> WriteU32;
|
||||
|
||||
/// Writes a signed 32-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_i32(&mut self, n: i32) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write signed 32-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_i32(267).await?;
|
||||
/// writer.write_i32(1205419366).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_i32(&mut self, n: i32) -> WriteI32;
|
||||
|
||||
/// Writes an unsigned 64-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_u64(&mut self, n: u64) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 64-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u64(918733457491587).await?;
|
||||
/// writer.write_u64(143).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_u64(&mut self, n: u64) -> WriteU64;
|
||||
|
||||
/// Writes an signed 64-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_i64(&mut self, n: i64) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write signed 64-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_i64(i64::min_value()).await?;
|
||||
/// writer.write_i64(i64::max_value()).await?;
|
||||
///
|
||||
/// assert_eq!(writer, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff");
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_i64(&mut self, n: i64) -> WriteI64;
|
||||
|
||||
/// Writes an unsigned 128-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_u128(&mut self, n: u128) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write unsigned 128-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_u128(16947640962301618749969007319746179).await?;
|
||||
///
|
||||
/// assert_eq!(writer, vec![
|
||||
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
|
||||
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
|
||||
/// ]);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_u128(&mut self, n: u128) -> WriteU128;
|
||||
|
||||
/// Writes an signed 128-bit integer in big-endian order to the
|
||||
/// underlying writer.
|
||||
///
|
||||
/// Equivalent to:
|
||||
///
|
||||
/// ```ignore
|
||||
/// async fn write_i128(&mut self, n: i128) -> io::Result<()>;
|
||||
/// ```
|
||||
///
|
||||
/// It is recommended to use a buffered writer to avoid excessive
|
||||
/// syscalls.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns the same errors as [`AsyncWriteExt::write_all`].
|
||||
///
|
||||
/// [`AsyncWriteExt::write_all`]: AsyncWriteExt::write_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write signed 128-bit integers to a `AsyncWrite`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use tokio::io::{self, AsyncWriteExt};
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> io::Result<()> {
|
||||
/// let mut writer = Vec::new();
|
||||
///
|
||||
/// writer.write_i128(i128::min_value()).await?;
|
||||
///
|
||||
/// assert_eq!(writer, vec![
|
||||
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
|
||||
/// 0, 0, 0, 0, 0, 0, 0, 0
|
||||
/// ]);
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn write_i128(&mut self, n: i128) -> WriteI128;
|
||||
}
|
||||
|
||||
/// Flush this output stream, ensuring that all intermediately buffered
|
||||
/// contents reach their destination.
|
||||
///
|
||||
|
@ -34,6 +34,7 @@ cfg_io_util! {
|
||||
|
||||
mod read;
|
||||
mod read_exact;
|
||||
mod read_int;
|
||||
mod read_line;
|
||||
|
||||
mod read_to_end;
|
||||
@ -60,6 +61,8 @@ cfg_io_util! {
|
||||
|
||||
mod write;
|
||||
mod write_all;
|
||||
mod write_int;
|
||||
|
||||
|
||||
// used by `BufReader` and `BufWriter`
|
||||
// https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/io.rs#L1
|
||||
|
122
tokio/src/io/util/read_int.rs
Normal file
122
tokio/src/io/util/read_int.rs
Normal file
@ -0,0 +1,122 @@
|
||||
use crate::io::AsyncRead;
|
||||
|
||||
use bytes::Buf;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::io::ErrorKind::UnexpectedEof;
|
||||
use std::mem::size_of;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
macro_rules! reader {
|
||||
($name:ident, $ty:ty, $reader:ident) => {
|
||||
reader!($name, $ty, $reader, size_of::<$ty>());
|
||||
};
|
||||
($name:ident, $ty:ty, $reader:ident, $bytes:expr) => {
|
||||
pin_project! {
|
||||
#[doc(hidden)]
|
||||
pub struct $name<R> {
|
||||
#[pin]
|
||||
src: R,
|
||||
buf: [u8; $bytes],
|
||||
read: u8,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> $name<R> {
|
||||
pub(crate) fn new(src: R) -> Self {
|
||||
$name {
|
||||
src,
|
||||
buf: [0; $bytes],
|
||||
read: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Future for $name<R>
|
||||
where
|
||||
R: AsyncRead,
|
||||
{
|
||||
type Output = io::Result<$ty>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut me = self.project();
|
||||
|
||||
if *me.read == $bytes as u8 {
|
||||
return Poll::Ready(Ok(Buf::$reader(&mut &me.buf[..])));
|
||||
}
|
||||
|
||||
while *me.read < $bytes as u8 {
|
||||
*me.read += match me.src
|
||||
.as_mut()
|
||||
.poll_read(cx, &mut me.buf[*me.read as usize..])
|
||||
{
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())),
|
||||
Poll::Ready(Ok(0)) => {
|
||||
return Poll::Ready(Err(UnexpectedEof.into()));
|
||||
}
|
||||
Poll::Ready(Ok(n)) => n as u8,
|
||||
};
|
||||
}
|
||||
|
||||
let num = Buf::$reader(&mut &me.buf[..]);
|
||||
|
||||
Poll::Ready(Ok(num))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! reader8 {
|
||||
($name:ident, $ty:ty) => {
|
||||
pin_project! {
|
||||
/// Future returned from `read_u8`
|
||||
#[doc(hidden)]
|
||||
pub struct $name<R> {
|
||||
#[pin]
|
||||
reader: R,
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> $name<R> {
|
||||
pub(crate) fn new(reader: R) -> $name<R> {
|
||||
$name { reader }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Future for $name<R>
|
||||
where
|
||||
R: AsyncRead,
|
||||
{
|
||||
type Output = io::Result<$ty>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let me = self.project();
|
||||
|
||||
let mut buf = [0; 1];
|
||||
match me.reader.poll_read(cx, &mut buf[..]) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
|
||||
Poll::Ready(Ok(0)) => Poll::Ready(Err(UnexpectedEof.into())),
|
||||
Poll::Ready(Ok(1)) => Poll::Ready(Ok(buf[0] as $ty)),
|
||||
Poll::Ready(Ok(_)) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
reader8!(ReadU8, u8);
|
||||
reader8!(ReadI8, i8);
|
||||
|
||||
reader!(ReadU16, u16, get_u16);
|
||||
reader!(ReadU32, u32, get_u32);
|
||||
reader!(ReadU64, u64, get_u64);
|
||||
reader!(ReadU128, u128, get_u128);
|
||||
|
||||
reader!(ReadI16, i16, get_i16);
|
||||
reader!(ReadI32, i32, get_i32);
|
||||
reader!(ReadI64, i64, get_i64);
|
||||
reader!(ReadI128, i128, get_i128);
|
121
tokio/src/io/util/write_int.rs
Normal file
121
tokio/src/io/util/write_int.rs
Normal file
@ -0,0 +1,121 @@
|
||||
use crate::io::AsyncWrite;
|
||||
|
||||
use bytes::BufMut;
|
||||
use pin_project_lite::pin_project;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::mem::size_of;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
macro_rules! writer {
|
||||
($name:ident, $ty:ty, $writer:ident) => {
|
||||
writer!($name, $ty, $writer, size_of::<$ty>());
|
||||
};
|
||||
($name:ident, $ty:ty, $writer:ident, $bytes:expr) => {
|
||||
pin_project! {
|
||||
#[doc(hidden)]
|
||||
pub struct $name<W> {
|
||||
#[pin]
|
||||
dst: W,
|
||||
buf: [u8; $bytes],
|
||||
written: u8,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> $name<W> {
|
||||
pub(crate) fn new(w: W, value: $ty) -> Self {
|
||||
let mut writer = $name {
|
||||
buf: [0; $bytes],
|
||||
written: 0,
|
||||
dst: w,
|
||||
};
|
||||
BufMut::$writer(&mut &mut writer.buf[..], value);
|
||||
writer
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Future for $name<W>
|
||||
where
|
||||
W: AsyncWrite,
|
||||
{
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut me = self.project();
|
||||
|
||||
if *me.written == $bytes as u8 {
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
|
||||
while *me.written < $bytes as u8 {
|
||||
*me.written += match me.dst
|
||||
.as_mut()
|
||||
.poll_write(cx, &me.buf[*me.written as usize..])
|
||||
{
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())),
|
||||
Poll::Ready(Ok(n)) => n as u8,
|
||||
};
|
||||
}
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! writer8 {
|
||||
($name:ident, $ty:ty) => {
|
||||
pin_project! {
|
||||
#[doc(hidden)]
|
||||
pub struct $name<W> {
|
||||
#[pin]
|
||||
dst: W,
|
||||
byte: $ty,
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> $name<W> {
|
||||
pub(crate) fn new(dst: W, byte: $ty) -> Self {
|
||||
Self {
|
||||
dst,
|
||||
byte,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Future for $name<W>
|
||||
where
|
||||
W: AsyncWrite,
|
||||
{
|
||||
type Output = io::Result<()>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let me = self.project();
|
||||
|
||||
let buf = [*me.byte as u8];
|
||||
|
||||
match me.dst.poll_write(cx, &buf[..]) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
|
||||
Poll::Ready(Ok(0)) => Poll::Pending,
|
||||
Poll::Ready(Ok(1)) => Poll::Ready(Ok(())),
|
||||
Poll::Ready(Ok(_)) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
writer8!(WriteU8, u8);
|
||||
writer8!(WriteI8, i8);
|
||||
|
||||
writer!(WriteU16, u16, put_u16);
|
||||
writer!(WriteU32, u32, put_u32);
|
||||
writer!(WriteU64, u64, put_u64);
|
||||
writer!(WriteU128, u128, put_u128);
|
||||
|
||||
writer!(WriteI16, i16, put_i16);
|
||||
writer!(WriteI32, i32, put_i32);
|
||||
writer!(WriteI64, i64, put_i64);
|
||||
writer!(WriteI128, i128, put_i128);
|
Loading…
x
Reference in New Issue
Block a user