Compare commits

..

2 Commits

Author SHA1 Message Date
GIKExe
9a15eb92e5 до Configuration 2025-05-08 12:16:19 +03:00
GIKExe
1124373d21 Async/Sunc Reader/Writer 2025-05-08 11:03:31 +03:00
9 changed files with 300 additions and 132 deletions

24
Cargo.lock generated
View File

@ -178,7 +178,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"libz-sys",
"miniz_oxide", "miniz_oxide",
] ]
@ -286,17 +285,6 @@ version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libz-sys"
version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -398,12 +386,6 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pkg-config"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -648,12 +630,6 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"

View File

@ -5,7 +5,7 @@ edition = "2024"
[dependencies] [dependencies]
tokio = {version = "1.45.0", features = ["full"]} tokio = {version = "1.45.0", features = ["full"]}
flate2 = {version = "1.1.1", features = ["zlib"]} flate2 = {version = "1.1.1"}
serde = {version = "1.0.219", features = ["derive"]} serde = {version = "1.0.219", features = ["derive"]}
serde_with = "3.12.0" serde_with = "3.12.0"
serde_json = "1.0.140" serde_json = "1.0.140"

View File

@ -1,7 +1,7 @@
use tokio::net::TcpStream; use tokio::{net::TcpStream, time::Sleep};
use crate::data::{clientbound, serverbound, DataError, AsyncReader, DataWriter, Packet, TextComponentBuilder}; use crate::data::{clientbound, serverbound, AsyncReader, AsyncWriter, DataError, Packet, Reader, TextComponentBuilder, Writer};
#[derive(Debug)] #[derive(Debug)]
@ -33,10 +33,10 @@ pub async fn main(mut stream: TcpStream) {
async fn read_first_packet(stream: &mut TcpStream) -> Result<(), PacketError> { async fn read_first_packet(stream: &mut TcpStream) -> Result<(), PacketError> {
let mut packet = stream.read_packet(None).await?; let mut packet = stream.read_packet(None).await?;
if packet.id() != 0 { return Err(PacketError::WrongPacketID);} if packet.id() != 0 { return Err(PacketError::WrongPacketID);}
let version = packet.read_varint().await?; let version = packet.read_varint()?;
let host = packet.read_string().await?; let host = packet.read_string()?;
let port = packet.read_short().await?; let port = packet.read_short()?;
let ns = packet.read_varint().await?; let ns = packet.read_varint()?;
if version != 770 { if version != 770 {
let mut packet = Packet::empty(0x00); let mut packet = Packet::empty(0x00);
@ -45,15 +45,18 @@ async fn read_first_packet(stream: &mut TcpStream) -> Result<(), PacketError> {
.text("Версия игры отличается от 1.21.5") .text("Версия игры отличается от 1.21.5")
.color("red") .color("red")
.build(); .build();
packet.write_string(&component.as_json()?).await?; packet.write_string(&component.as_json()?)?;
return Ok(stream.write_packet(packet, None).await?); return Ok(stream.write_packet(packet, None).await?);
} }
match ns { match ns {
1 => the_status(stream).await, 1 => return the_status(stream).await,
2 => the_login(stream, (version, host, port)).await, 2 => the_login(stream, (version, host, port)).await?,
_ => Err(PacketError::NextStateIncorrect) _ => return Err(PacketError::NextStateIncorrect)
} };
the_configuration(stream).await?;
Ok(())
} }
async fn the_status(stream: &mut TcpStream) -> Result<(), PacketError> { async fn the_status(stream: &mut TcpStream) -> Result<(), PacketError> {
@ -70,13 +73,13 @@ async fn the_status(stream: &mut TcpStream) -> Result<(), PacketError> {
\"online\": 1 \"online\": 1
} }
}"; }";
p.write_string(status).await?; p.write_string(status)?;
stream.write_packet(p, None).await?; stream.write_packet(p, None).await?;
let mut packet = stream.read_packet(None).await?; let mut packet = stream.read_packet(None).await?;
if packet.id() != 1 { return Err(PacketError::WrongPacketID); } if packet.id() != 1 { return Err(PacketError::WrongPacketID); }
let mut p = Packet::empty(clientbound::status::PONG_RESPONSE); let mut p = Packet::empty(clientbound::status::PONG_RESPONSE);
p.write_long(packet.read_long().await?).await?; p.write_long(packet.read_long()?)?;
stream.write_packet(p, None).await?; stream.write_packet(p, None).await?;
Ok(()) Ok(())
@ -91,7 +94,7 @@ async fn the_login(stream: &mut TcpStream, data: (i32, String, u16)) -> Result<(
.text("Версия игры отличается от 1.21.5") .text("Версия игры отличается от 1.21.5")
.color("red") .color("red")
.build(); .build();
packet.write_string(&component.as_json()?).await?; packet.write_string(&component.as_json()?)?;
return Ok(stream.write_packet(packet, None).await?); return Ok(stream.write_packet(packet, None).await?);
} }
@ -109,15 +112,32 @@ async fn the_login(stream: &mut TcpStream, data: (i32, String, u16)) -> Result<(
let mut packet = stream.read_packet(None).await?; let mut packet = stream.read_packet(None).await?;
if packet.id() != serverbound::login::START { return Err(PacketError::WrongPacketID); } if packet.id() != serverbound::login::START { return Err(PacketError::WrongPacketID); }
let username = packet.read_string().await?; let username = packet.read_string()?;
let uuid = packet.read_uuid().await?; let uuid = packet.read_uuid()?;
println!("Адрес клиента: {:?}", stream.peer_addr()); // println!("Адрес клиента: {}", stream.peer_addr().unwrap());
println!("Адрес сервера: {}:{}", data.1, data.2); // println!("Адрес сервера: {}:{}", data.1, data.2);
println!("Username: {username}\n UUID: {:X}", uuid); // println!("Username: {username}\nUUID: {:X}", uuid);
let threshold = 512usize;
let mut packet = Packet::empty(clientbound::login::SET_COMPRESSION); let mut packet = Packet::empty(clientbound::login::SET_COMPRESSION);
packet.write_varint(512).await?; packet.write_varint(threshold as i32)?;
stream.write_packet(packet, None).await?;
let mut packet = Packet::empty(clientbound::login::SUCCESS);
packet.write_uuid(uuid)?;
packet.write_string(&username)?;
packet.write_varint(0)?;
stream.write_packet(packet, Some(threshold)).await?;
let packet = stream.read_packet(Some(threshold)).await?;
if packet.id() != serverbound::login::ACKNOWLEDGED { return Err(PacketError::WrongPacketID); }
Ok(()) Ok(())
}
async fn the_configuration(stream: &mut TcpStream) -> Result<(), PacketError> {
loop {
}
} }

View File

@ -1,13 +1,30 @@
use std::io::{Cursor, ErrorKind, Read}; use std::io::{Cursor, ErrorKind};
use tokio::io::{AsyncRead, AsyncReadExt}; use tokio::{io::AsyncReadExt, net::TcpStream};
use crate::inet::InetError; use crate::inet::InetError;
use super::{decompress, packet::Packet, DataError}; use super::{decompress, packet::Packet, DataError, Reader};
impl AsyncReader for TcpStream {
async fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> {
let mut buf = vec![0; size];
match AsyncReadExt::read_exact(self, &mut buf).await {
Ok(_) => Ok(buf),
Err(e) => match e.kind() {
ErrorKind::UnexpectedEof | ErrorKind::BrokenPipe | ErrorKind::ConnectionReset => {
Err(DataError::Inet(InetError::ConnectionClosed))
}
_ => {
Err(DataError::ReadError)
},
}
}
}
}
pub trait AsyncReader { pub trait AsyncReader {
async fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError>; async fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError>;
@ -51,7 +68,7 @@ pub trait AsyncReader {
data = self.read_bytes(packet_lenght).await?; data = self.read_bytes(packet_lenght).await?;
} }
let mut cursor = Cursor::new(data); let mut cursor = Cursor::new(data);
let id = cursor.read_varint().await?; let id = cursor.read_varint()?;
Ok(Packet::new(id as u8, cursor)) Ok(Packet::new(id as u8, cursor))
} }
@ -86,21 +103,4 @@ pub trait AsyncReader {
self.read_bytes(16).await?.try_into().unwrap() self.read_bytes(16).await?.try_into().unwrap()
)) ))
} }
}
impl<R: AsyncRead + Unpin> AsyncReader for R {
async fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> {
let mut buf = vec![0; size];
match AsyncReadExt::read_exact(self, &mut buf).await {
Ok(_) => Ok(buf),
Err(e) => match e.kind() {
ErrorKind::UnexpectedEof | ErrorKind::BrokenPipe | ErrorKind::ConnectionReset => {
Err(DataError::Inet(InetError::ConnectionClosed))
}
_ => {
Err(DataError::ReadError)
},
}
}
}
} }

96
src/data/async_writer.rs Normal file
View File

@ -0,0 +1,96 @@
use std::io::Write;
use tokio::{io::AsyncWriteExt, net::TcpStream};
use super::{compress, packet::Packet, DataError, Writer};
impl AsyncWriter for TcpStream {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError> {
AsyncWriteExt::write_all(self, bytes).await.or(Err(DataError::WriteError))
}
}
pub trait AsyncWriter {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError>;
async fn write_byte(&mut self, value: u8) -> Result<(), DataError> {
self.write_bytes(&[value]).await
}
async fn write_signed_byte(&mut self, value: i8) -> Result<(), DataError> {
self.write_byte(value as u8).await
}
async fn write_varint_size(&mut self, value: i32) -> Result<usize, DataError> {
let mut _value = value as u32;
let mut position = 0;
loop {
let mut byte = (_value & 127) as u8;
position += 1; _value >>= 7;
if _value != 0 { byte += 128; };
self.write_byte(byte).await?;
if _value == 0 { return Ok(position) }
}
}
async fn write_varint(&mut self, value: i32) -> Result<(), DataError> {
self.write_varint_size(value).await?; Ok(())
}
async fn write_packet(&mut self, packet: Packet, threshold: Option<usize>)
-> Result<(), DataError> {
let mut buf = Vec::new();
let mut data_buf = Vec::new();
data_buf.write_varint((packet.id() as u32) as i32)?;
data_buf.write_bytes(packet.get_bytes())?;
if let Some(threshold) = threshold {
let mut packet_buf = Vec::new();
if data_buf.len() > threshold {
packet_buf.write_varint(data_buf.len() as i32)?;
let compressed_data = compress(&data_buf)?;
Write::write_all(&mut packet_buf, &compressed_data).or(Err(DataError::WriteError))?;
} else {
packet_buf.write_varint(0)?;
packet_buf.write_bytes(&data_buf)?;
}
buf.write_varint(packet_buf.len() as i32)?;
buf.write_bytes(&packet_buf)?;
} else {
buf.write_varint(data_buf.len() as i32)?;
buf.write_bytes(&data_buf)?;
}
self.write_bytes(&buf).await?;
Ok(())
}
async fn write_short(&mut self, value: u16) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
async fn write_signed_short(&mut self, value: i16) -> Result<(), DataError> {
self.write_short(value as u16).await
}
async fn write_string(&mut self, value: &str) -> Result<(), DataError> {
self.write_varint(value.len() as i32).await?;
self.write_bytes(value.as_bytes()).await?;
Ok(())
}
async fn write_long(&mut self, value: u64) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
async fn write_signed_long(&mut self, value: i64) -> Result<(), DataError> {
self.write_long(value as u64).await
}
async fn write_uuid(&mut self, value: u128) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await
}
}

View File

@ -1,10 +1,14 @@
use std::io::Read; use std::io::{Read, Write};
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
use crate::inet::InetError; use crate::inet::InetError;
mod async_reader; mod async_reader;
mod reader; mod reader;
mod async_writer;
mod writer; mod writer;
mod packet; mod packet;
mod packet_id; mod packet_id;
mod component; mod component;
@ -28,9 +32,15 @@ pub fn decompress(bytes: &[u8]) -> Result<Vec<u8>, DataError> {
Ok(output) Ok(output)
} }
pub fn compress(bytes: &[u8]) -> Result<Vec<u8>, DataError> {
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(1));
encoder.write_all(bytes).or(Err(DataError::ZlibError))?;
encoder.finish().or(Err(DataError::ZlibError))
}
pub use async_reader::*; pub use async_reader::*;
pub use reader::*; pub use reader::*;
use flate2::bufread::ZlibDecoder; pub use async_writer::*;
pub use writer::*; pub use writer::*;
pub use packet::*; pub use packet::*;
pub use packet_id::{clientbound, serverbound}; pub use packet_id::{clientbound, serverbound};

View File

@ -1,6 +1,6 @@
use std::io::Cursor; use std::io::Cursor;
use super::{DataError, async_reader::AsyncReader, writer::DataWriter}; use super::{DataError, Reader, Writer};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Packet { pub struct Packet {
@ -84,14 +84,14 @@ impl From<Packet> for Cursor<Vec<u8>> {
} }
} }
impl AsyncReader for Packet { impl Reader for Packet {
async fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> { fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> {
self.cursor.read_bytes(size).await self.cursor.read_bytes(size)
} }
} }
impl DataWriter for Packet { impl Writer for Packet {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError> { fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError> {
self.cursor.write_bytes(bytes).await self.cursor.write_bytes(bytes)
} }
} }

View File

@ -1,14 +1,9 @@
use std::io::Read; use std::io::{Cursor, Read};
use super::DataError; use super::{decompress, DataError, Packet};
pub trait Reader {
fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError>;
}
impl<R: Read> Reader for R { impl<R: Read> Reader for R {
fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> { fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError> {
let mut buf = vec![0; size]; let mut buf = vec![0; size];
@ -17,4 +12,84 @@ impl<R: Read> Reader for R {
Err(_) => Err(DataError::ReadError) Err(_) => Err(DataError::ReadError)
} }
} }
}
pub trait Reader {
fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, DataError>;
fn read_byte(&mut self) -> Result<u8, DataError> {
Ok(self.read_bytes(1)?[0])
}
fn read_signed_byte(&mut self) -> Result<i8, DataError> {
Ok(self.read_byte()? as i8)
}
fn read_varint_size(&mut self) -> Result<(i32, usize), DataError> {
let mut value = 0;
let mut position = 0;
loop {
let byte = self.read_byte()?;
value |= ((byte & 0x7F) as i32) << (position * 7);
if (byte & 0x80) == 0 {
return Ok((value, position as usize));
};
position += 1;
if position >= 5 {
return Err(DataError::VarIntIsSoBig);
};
}
}
fn read_varint(&mut self) -> Result<i32, DataError> {
Ok(self.read_varint_size()?.0)
}
fn read_packet(&mut self, threshold: Option<usize>)
-> Result<Packet, DataError> {
let mut data: Vec<u8>;
let packet_lenght = self.read_varint()? as usize;
if threshold.is_some() {
let data_lenght = self.read_varint_size()?;
data = self.read_bytes(packet_lenght - data_lenght.1)?;
if data_lenght.0 != 0 { data = decompress(&data)?; }
} else {
data = self.read_bytes(packet_lenght)?;
}
let mut cursor = Cursor::new(data);
let id = cursor.read_varint()?;
Ok(Packet::new(id as u8, cursor))
}
fn read_short(&mut self) -> Result<u16, DataError> {
Ok(u16::from_be_bytes(
self.read_bytes(2)?.try_into().unwrap()
))
}
fn read_signed_short(&mut self) -> Result<i16, DataError> {
Ok(self.read_short()? as i16)
}
fn read_string(&mut self) -> Result<String, DataError> {
let size = self.read_varint()?;
let vec = self.read_bytes(size as usize)?;
String::from_utf8(vec).or( Err(DataError::StringDecodeError))
}
fn read_long(&mut self) -> Result<u64, DataError> {
Ok(u64::from_be_bytes(
self.read_bytes(8)?.try_into().unwrap()
))
}
fn read_signed_long(&mut self) -> Result<i64, DataError> {
Ok(self.read_long()? as i64)
}
fn read_uuid(&mut self) -> Result<u128, DataError> {
Ok(u128::from_be_bytes(
self.read_bytes(16)?.try_into().unwrap()
))
}
} }

View File

@ -1,103 +1,94 @@
use std::io::{Cursor, Seek, SeekFrom, Write}; use std::io::Write;
use flate2::{write::ZlibEncoder, Compression}; use super::{compress, DataError, Packet};
use tokio::io::{AsyncWrite, AsyncWriteExt};
use super::{packet::{self, Packet}, DataError};
pub fn compress(bytes: &[u8], compression: u32) -> Result<Vec<u8>, DataError> { impl<W: Write> Writer for W {
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression)); fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError> {
encoder.write_all(bytes).or(Err(DataError::ZlibError))?; self.write_all(bytes).or(Err(DataError::WriteError))
encoder.finish().or(Err(DataError::ZlibError)) }
} }
pub trait DataWriter { pub trait Writer {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError>; fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError>;
async fn write_byte(&mut self, value: u8) -> Result<(), DataError> { fn write_byte(&mut self, value: u8) -> Result<(), DataError> {
self.write_bytes(&[value]).await self.write_bytes(&[value])
} }
async fn write_signed_byte(&mut self, value: i8) -> Result<(), DataError> { fn write_signed_byte(&mut self, value: i8) -> Result<(), DataError> {
self.write_byte(value as u8).await self.write_byte(value as u8)
} }
async fn write_varint_size(&mut self, value: i32) -> Result<usize, DataError> { fn write_varint_size(&mut self, value: i32) -> Result<usize, DataError> {
let mut _value = value as u32; let mut _value = value as u32;
let mut position = 0; let mut position = 0;
loop { loop {
let mut byte = (_value & 127) as u8; let mut byte = (_value & 127) as u8;
position += 1; _value >>= 7; position += 1; _value >>= 7;
if _value != 0 { byte += 128; }; if _value != 0 { byte += 128; };
self.write_byte(byte).await?; self.write_byte(byte)?;
if _value == 0 { return Ok(position) } if _value == 0 { return Ok(position) }
} }
} }
async fn write_varint(&mut self, value: i32) -> Result<(), DataError> { fn write_varint(&mut self, value: i32) -> Result<(), DataError> {
self.write_varint_size(value).await?; Ok(()) self.write_varint_size(value)?; Ok(())
} }
async fn write_packet(&mut self, packet: Packet, threshold: Option<usize>) fn write_packet(&mut self, packet: Packet, threshold: Option<usize>)
-> Result<(), DataError> { -> Result<(), DataError> {
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut data_buf = Vec::new(); let mut data_buf = Vec::new();
data_buf.write_varint((packet.id() as u32) as i32).await?; data_buf.write_varint((packet.id() as u32) as i32)?;
data_buf.write_bytes(packet.get_bytes()).await?; data_buf.write_bytes(packet.get_bytes())?;
if let Some(threshold) = threshold { if let Some(threshold) = threshold {
let mut packet_buf = Vec::new(); let mut packet_buf = Vec::new();
if data_buf.len() > threshold { if data_buf.len() > threshold {
packet_buf.write_varint(data_buf.len() as i32).await?; packet_buf.write_varint(data_buf.len() as i32)?;
let compressed_data = compress(&data_buf, 5)?; let compressed_data = compress(&data_buf)?;
Write::write_all(&mut packet_buf, &compressed_data).or(Err(DataError::WriteError))?; Write::write_all(&mut packet_buf, &compressed_data).or(Err(DataError::WriteError))?;
} else { } else {
packet_buf.write_varint(0).await?; packet_buf.write_varint(0)?;
packet_buf.write_bytes(&data_buf).await?; packet_buf.write_bytes(&data_buf)?;
} }
buf.write_varint(packet_buf.len() as i32).await?; buf.write_varint(packet_buf.len() as i32)?;
buf.write_bytes(&packet_buf).await?; buf.write_bytes(&packet_buf)?;
} else { } else {
buf.write_varint(data_buf.len() as i32).await?; buf.write_varint(data_buf.len() as i32)?;
buf.write_bytes(&data_buf).await?; buf.write_bytes(&data_buf)?;
} }
self.write_bytes(&buf).await?; self.write_bytes(&buf)?;
Ok(()) Ok(())
} }
async fn write_short(&mut self, value: u16) -> Result<(), DataError> { fn write_short(&mut self, value: u16) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await self.write_bytes(&value.to_be_bytes())
} }
async fn write_signed_short(&mut self, value: i16) -> Result<(), DataError> { fn write_signed_short(&mut self, value: i16) -> Result<(), DataError> {
self.write_short(value as u16).await self.write_short(value as u16)
} }
async fn write_string(&mut self, value: &str) -> Result<(), DataError> { fn write_string(&mut self, value: &str) -> Result<(), DataError> {
self.write_varint(value.len() as i32).await?; self.write_varint(value.len() as i32)?;
self.write_bytes(value.as_bytes()).await?; self.write_bytes(value.as_bytes())?;
Ok(()) Ok(())
} }
async fn write_long(&mut self, value: u64) -> Result<(), DataError> { fn write_long(&mut self, value: u64) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await self.write_bytes(&value.to_be_bytes())
} }
async fn write_signed_long(&mut self, value: i64) -> Result<(), DataError> { fn write_signed_long(&mut self, value: i64) -> Result<(), DataError> {
self.write_long(value as u64).await self.write_long(value as u64)
} }
async fn write_uuid(&mut self, value: u128) -> Result<(), DataError> { fn write_uuid(&mut self, value: u128) -> Result<(), DataError> {
self.write_bytes(&value.to_be_bytes()).await self.write_bytes(&value.to_be_bytes())
}
}
impl<W: AsyncWrite + Unpin> DataWriter for W {
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DataError> {
AsyncWriteExt::write_all(self, bytes).await.or(Err(DataError::WriteError))
} }
} }