mirror of
https://github.com/OMGeeky/mc-server-rs-sample.git
synced 2026-01-22 02:21:37 +01:00
try to fix some status response stuff
This commit is contained in:
46
Cargo.lock
generated
46
Cargo.lock
generated
@@ -123,6 +123,12 @@ version = "0.3.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.162"
|
version = "0.2.162"
|
||||||
@@ -145,6 +151,8 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@@ -274,12 +282,50 @@ version = "0.1.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.215"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.215"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.132"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.2"
|
version = "1.4.2"
|
||||||
|
|||||||
@@ -10,3 +10,5 @@ tokio = { version = "1.41.1", features = ["rt", "rt-multi-thread", "macros", "fu
|
|||||||
|
|
||||||
tokio-util = { version = "0.7.0", features = ["full"] }
|
tokio-util = { version = "0.7.0", features = ["full"] }
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_json = "1.0"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![allow(unused)]
|
||||||
pub mod protocols;
|
pub mod protocols;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
@@ -5,10 +6,10 @@ pub mod utils;
|
|||||||
use crate::types::string::McString;
|
use crate::types::string::McString;
|
||||||
use crate::types::var_int::VarInt;
|
use crate::types::var_int::VarInt;
|
||||||
use crate::types::{McRead, McRustRepr};
|
use crate::types::{McRead, McRustRepr};
|
||||||
use crate::utils::RWStreamWithLimit;
|
use crate::utils::{MyAsyncReadExt, RWStreamWithLimit};
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -38,6 +39,7 @@ enum ConnectionState {
|
|||||||
Status = 1,
|
Status = 1,
|
||||||
Login = 2,
|
Login = 2,
|
||||||
Transfer = 3,
|
Transfer = 3,
|
||||||
|
///Internal use
|
||||||
Closed = -1,
|
Closed = -1,
|
||||||
}
|
}
|
||||||
struct Connection {
|
struct Connection {
|
||||||
@@ -87,6 +89,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.connection_state = ConnectionState::Closed;
|
self.connection_state = ConnectionState::Closed;
|
||||||
|
dbg!(&self.tcp_stream.shutdown().await);
|
||||||
println!("Got an error during package handling: {e}");
|
println!("Got an error during package handling: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +109,7 @@ impl Connection {
|
|||||||
.await
|
.await
|
||||||
.map_err(|_| "Could not read string".to_string())?;
|
.map_err(|_| "Could not read string".to_string())?;
|
||||||
println!("address: '{}'", address.as_rs());
|
println!("address: '{}'", address.as_rs());
|
||||||
stream.read_exact(&mut [0, 2]).await.unwrap(); //server port. Unused
|
stream.discard(2).await.unwrap(); //server port. Unused
|
||||||
let next_state_id = VarInt::read_stream(stream).await?;
|
let next_state_id = VarInt::read_stream(stream).await?;
|
||||||
println!("next state: {}", next_state_id.as_rs());
|
println!("next state: {}", next_state_id.as_rs());
|
||||||
let next_state = FromPrimitive::from_i32(next_state_id.to_rs());
|
let next_state = FromPrimitive::from_i32(next_state_id.to_rs());
|
||||||
|
|||||||
@@ -3,22 +3,23 @@ use num_derive::FromPrimitive;
|
|||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive)]
|
||||||
pub enum Protocols {
|
pub enum Protocol {
|
||||||
Status = 0x00,
|
Status = 0x00,
|
||||||
Ping = 0x01,
|
Ping = 0x01,
|
||||||
CustomReportDetails = 0x7a,
|
CustomReportDetails = 0x7a,
|
||||||
}
|
}
|
||||||
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
|
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
protocol: Protocols,
|
protocol: Protocol,
|
||||||
stream: &mut RWStreamWithLimit<'_, T>,
|
stream: &mut RWStreamWithLimit<'_, T>,
|
||||||
// bytes_left_in_package: &mut i32,
|
// bytes_left_in_package: &mut i32,
|
||||||
) -> Result<(), bool> {
|
) -> Result<(), bool> {
|
||||||
match protocol {
|
match protocol {
|
||||||
Protocols::Status => status::Protocol::handle(stream).await?,
|
Protocol::Status => status::Protocol::handle(stream).await?,
|
||||||
Protocols::Ping => {}
|
Protocol::Ping => ping::Protocol::handle(stream).await?,
|
||||||
Protocols::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?,
|
Protocol::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
mod custom_report_details;
|
mod custom_report_details;
|
||||||
|
mod ping;
|
||||||
mod status;
|
mod status;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::types::string::McString;
|
||||||
use crate::types::var_int::VarInt;
|
use crate::types::var_int::VarInt;
|
||||||
use crate::types::McRead;
|
use crate::types::McRead;
|
||||||
use crate::utils::RWStreamWithLimit;
|
use crate::utils::RWStreamWithLimit;
|
||||||
@@ -10,33 +11,22 @@ impl Protocol {
|
|||||||
stream: &mut RWStreamWithLimit<'_, T>,
|
stream: &mut RWStreamWithLimit<'_, T>,
|
||||||
// bytes_left_in_package: &mut i32,
|
// bytes_left_in_package: &mut i32,
|
||||||
) -> Result<(), bool> {
|
) -> Result<(), bool> {
|
||||||
|
println!("Some custom report detail stuff...");
|
||||||
let count = VarInt::read_stream(stream).await.map_err(|x| {
|
let count = VarInt::read_stream(stream).await.map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
true
|
true
|
||||||
})?;
|
})?;
|
||||||
dbg!(&count);
|
dbg!(&count);
|
||||||
let string_size = VarInt::read_stream(stream).await.map_err(|x| {
|
for i in 0..*count {
|
||||||
dbg!(x);
|
McString::<128>::read_stream(stream).await.map_err(|x| {
|
||||||
true
|
dbg!(x);
|
||||||
})?;
|
true
|
||||||
dbg!(&string_size);
|
})?;
|
||||||
stream.discard_unread().await.map_err(|x| {
|
McString::<4096>::read_stream(stream).await.map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
true
|
true
|
||||||
})?;
|
})?;
|
||||||
// for i in 0..*count {
|
}
|
||||||
// let title = McString::read_stream(stream).await.map_err(|x| {
|
Err(true)
|
||||||
// dbg!(x);
|
|
||||||
// })?;
|
|
||||||
// let description = McString::read_stream(stream).await.map_err(|x| {
|
|
||||||
// dbg!(x);
|
|
||||||
// })?;
|
|
||||||
// println!(
|
|
||||||
// "Read title & description fo some custom report ({i}): {}\n{}",
|
|
||||||
// title.as_rs(),
|
|
||||||
// description.as_rs()
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/protocols/ping.rs
Normal file
29
src/protocols/ping.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use crate::types::var_int::VarInt;
|
||||||
|
use crate::types::var_long::VarLong;
|
||||||
|
use crate::types::{McRead, McWrite};
|
||||||
|
use crate::utils::RWStreamWithLimit;
|
||||||
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
|
|
||||||
|
pub struct Protocol {}
|
||||||
|
|
||||||
|
impl Protocol {
|
||||||
|
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
|
stream: &mut RWStreamWithLimit<'_, T>,
|
||||||
|
) -> Result<(), bool> {
|
||||||
|
println!("Ping");
|
||||||
|
let v = stream.read_i64().await.map_err(|e| {
|
||||||
|
dbg!(e);
|
||||||
|
false
|
||||||
|
})?;
|
||||||
|
VarInt(0x01).write_stream(stream).await.map_err(|x| {
|
||||||
|
dbg!(x);
|
||||||
|
false
|
||||||
|
})?;
|
||||||
|
stream.write_i64(v).await.map_err(|e| {
|
||||||
|
dbg!(e);
|
||||||
|
false
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,58 +1,83 @@
|
|||||||
use crate::types::string::McString;
|
use crate::types::string::McString;
|
||||||
use crate::types::var_int::VarInt;
|
use crate::types::var_int::VarInt;
|
||||||
|
use crate::types::var_long::VarLong;
|
||||||
use crate::types::McWrite;
|
use crate::types::McWrite;
|
||||||
use crate::utils::RWStreamWithLimit;
|
use crate::utils::RWStreamWithLimit;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use serde_json::json;
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufWriter};
|
||||||
|
|
||||||
pub struct Protocol {}
|
pub struct Protocol {}
|
||||||
|
|
||||||
impl Protocol {
|
impl Protocol {
|
||||||
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
|
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
stream: &mut RWStreamWithLimit<'_, T>,
|
stream: &mut RWStreamWithLimit<'_, T>,
|
||||||
// bytes_left_in_package: &mut i32,
|
|
||||||
) -> Result<(), bool> {
|
) -> Result<(), bool> {
|
||||||
println!("Status");
|
println!("Status");
|
||||||
VarInt(0x01).write_stream(stream).await.map_err(|x| {
|
stream.discard_unread().await.map_err(|x| {
|
||||||
|
dbg!(x);
|
||||||
|
false
|
||||||
|
})?;
|
||||||
|
let string = Self::get_sample_result();
|
||||||
|
let mut total_size = 0;
|
||||||
|
let mut v = Vec::new();
|
||||||
|
let mut writer = BufWriter::new(&mut v);
|
||||||
|
|
||||||
|
//Package ID
|
||||||
|
total_size += VarInt(0x00).write_stream(&mut writer).await.map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
false
|
false
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
McString::<32767>::from_string(Self::get_sample_result())
|
//Status JSON
|
||||||
|
total_size += McString::<32767>::from_string(string)
|
||||||
|
.write_stream(&mut writer)
|
||||||
|
.await
|
||||||
|
.map_err(|x| {
|
||||||
|
dbg!(x);
|
||||||
|
false
|
||||||
|
})?;
|
||||||
|
writer.flush().await.unwrap();
|
||||||
|
|
||||||
|
println!("total size: {}: {:?}", total_size, &v);
|
||||||
|
//Size in front
|
||||||
|
VarInt(total_size as i32)
|
||||||
.write_stream(stream)
|
.write_stream(stream)
|
||||||
.await
|
.await
|
||||||
.map_err(|x| {
|
.map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
false
|
false
|
||||||
})?;
|
})?;
|
||||||
// stream.discard_unread().await.map_err(|x| {
|
//actually write the content to the stream, not just a local buffer
|
||||||
// dbg!(x);
|
stream.write_all(&v).await.map_err(|x| {
|
||||||
// false
|
dbg!(x);
|
||||||
// })?;
|
false
|
||||||
// *bytes_left_in_package = 0;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_sample_result() -> String {
|
fn get_sample_result() -> String {
|
||||||
"{
|
json!({
|
||||||
\"version\": {
|
"version": {
|
||||||
\"name\": \"1.21.2\",
|
"name": "1.21.2",
|
||||||
\"protocol\": 768
|
"protocol": 768
|
||||||
},
|
},
|
||||||
\"players\": {
|
"players": {
|
||||||
\"max\": 100,
|
"max": 100,
|
||||||
\"online\": 5,
|
"online": 5,
|
||||||
\"sample\": [
|
"sample": [
|
||||||
{
|
{
|
||||||
\"name\": \"thinkofdeath\",
|
"name": "thinkofdeath",
|
||||||
\"id\": \"4566e69f-c907-48ee-8d71-d7ba5aa00d20\"
|
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
\"description\": {
|
"description": {
|
||||||
\"text\": \"Hello, world!\"
|
"text": "Hello, world!"
|
||||||
},
|
},
|
||||||
\"favicon\": \"data:image/png;base64,<data>\",
|
// "favicon": "data:image/png;base64,<data>",
|
||||||
\"enforcesSecureChat\": false
|
"enforcesSecureChat": false,
|
||||||
}"
|
})
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,17 @@ pub struct McString<const MAX_SIZE: usize> {
|
|||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
impl<const MAX_SIZE: usize> McString<MAX_SIZE> {
|
impl<const MAX_SIZE: usize> McString<MAX_SIZE> {
|
||||||
fn measure_size(s: &str) -> usize {
|
pub fn measure_size(s: &str) -> usize {
|
||||||
s.len()
|
// 3. UTF-8 encoded byte length
|
||||||
|
let utf8_len = s.bytes().len();
|
||||||
|
|
||||||
|
// 5. Calculate total length (including VarInt prefix)
|
||||||
|
let varint_size = VarInt(utf8_len as i32).get_size();
|
||||||
|
if varint_size > 3 {
|
||||||
|
//TODO: This is not allowed
|
||||||
|
}
|
||||||
|
// println!("strlen: {}+({}?{})", varint_size, utf8_len, utf16_len);
|
||||||
|
varint_size + utf8_len
|
||||||
}
|
}
|
||||||
pub fn from_string(s: String) -> Self {
|
pub fn from_string(s: String) -> Self {
|
||||||
Self { value: s }
|
Self { value: s }
|
||||||
@@ -25,6 +34,7 @@ impl<const MAX_SIZE: usize> McRead for McString<MAX_SIZE> {
|
|||||||
dbg!(x);
|
dbg!(x);
|
||||||
})?;
|
})?;
|
||||||
let size = *max_size as usize;
|
let size = *max_size as usize;
|
||||||
|
println!("Reading string of length: {}", size);
|
||||||
|
|
||||||
// Check if the size exceeds the maximum allowed length (n)
|
// Check if the size exceeds the maximum allowed length (n)
|
||||||
if size > (MAX_SIZE * 3) + 3 {
|
if size > (MAX_SIZE * 3) + 3 {
|
||||||
@@ -35,10 +45,14 @@ impl<const MAX_SIZE: usize> McRead for McString<MAX_SIZE> {
|
|||||||
let actual_size = b.read(&mut bytes).await.map_err(|x| {
|
let actual_size = b.read(&mut bytes).await.map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
})?;
|
})?;
|
||||||
assert_eq!(size, actual_size);
|
|
||||||
let value = String::from_utf8(bytes).map_err(|x| {
|
let value = String::from_utf8(bytes).map_err(|x| {
|
||||||
dbg!(x);
|
dbg!(x);
|
||||||
})?;
|
})?;
|
||||||
|
assert_eq!(
|
||||||
|
size, actual_size,
|
||||||
|
"Did not read all that was to read {}",
|
||||||
|
value
|
||||||
|
);
|
||||||
Ok(Self { value })
|
Ok(Self { value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,10 +68,12 @@ impl<const MAX_SIZE: usize> McWrite for McString<MAX_SIZE> {
|
|||||||
{
|
{
|
||||||
let buf = self.value.as_bytes();
|
let buf = self.value.as_bytes();
|
||||||
let length = Self::measure_size(&self.value);
|
let length = Self::measure_size(&self.value);
|
||||||
VarInt(length as i32).write_stream(stream).await?;
|
println!("string length: {}", length);
|
||||||
|
let length_var_int = VarInt(length as i32);
|
||||||
|
let written = length_var_int.write_stream(stream).await?;
|
||||||
|
println!("Writing String to stream: '{}'", self.value);
|
||||||
stream.write_all(buf).await?;
|
stream.write_all(buf).await?;
|
||||||
Ok(length)
|
Ok(buf.len() + written)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<const MAX_SIZE: usize> McRustRepr for McString<MAX_SIZE> {
|
impl<const MAX_SIZE: usize> McRustRepr for McString<MAX_SIZE> {
|
||||||
|
|||||||
18
src/utils.rs
18
src/utils.rs
@@ -1,3 +1,4 @@
|
|||||||
|
use std::cmp::min;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
@@ -8,6 +9,23 @@ pub struct RWStreamWithLimit<'a, T: AsyncRead + AsyncWrite> {
|
|||||||
read_bytes_left: usize,
|
read_bytes_left: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> {
|
||||||
|
pub(crate) async fn discard(&mut self, bytes: usize) -> std::io::Result<usize> {
|
||||||
|
let bytes = min(bytes, self.read_bytes_left);
|
||||||
|
let read = self.stream.read_exact(&mut vec![0; bytes]).await?;
|
||||||
|
self.read_bytes_left -= read;
|
||||||
|
Ok(read)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) trait MyAsyncReadExt {
|
||||||
|
async fn discard(&mut self, bytes: usize) -> std::io::Result<usize>;
|
||||||
|
}
|
||||||
|
impl<T: AsyncRead + Unpin> MyAsyncReadExt for T {
|
||||||
|
async fn discard(&mut self, bytes: usize) -> std::io::Result<usize> {
|
||||||
|
self.read_exact(&mut vec![0; bytes]).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> {
|
impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> {
|
||||||
pub(crate) fn new(stream: &'a mut T, read_limit: usize) -> Self {
|
pub(crate) fn new(stream: &'a mut T, read_limit: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user