From 567c6f4f2c39976d170111b816806453636f8241 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 1 May 2022 21:54:03 -0500 Subject: [PATCH 1/4] Reduce usage of AsyncRead We already receive everything from the server when it tells us the length, so we can actually just treat the stream as a Read instead of an AsyncRead. --- Cargo.lock | 36 +- azalea-client/src/connect.rs | 2 +- azalea-nbt/Cargo.toml | 10 +- azalea-nbt/benches/my_benchmark.rs | 5 +- azalea-nbt/src/decode.rs | 83 ++-- azalea-nbt/tests/tests.rs | 62 +-- azalea-protocol/Cargo.toml | 2 +- azalea-protocol/packet-macros/src/lib.rs | 32 +- azalea-protocol/src/mc_buf/mod.rs | 114 +++-- azalea-protocol/src/mc_buf/read.rs | 407 +++++++----------- azalea-protocol/src/mc_buf/write.rs | 6 +- .../clientbound_declare_commands_packet.rs | 98 ++--- .../clientbound_player_abilities_packet.rs | 12 +- .../game/clientbound_player_info_packet.rs | 23 +- .../clientbound_player_position_packet.rs | 12 +- .../packets/game/clientbound_recipe_packet.rs | 12 +- .../clientbound_set_entity_data_packet.rs | 88 ++-- .../clientbound_update_attributes_packet.rs | 18 +- .../game/clientbound_update_recipes_packet.rs | 47 +- .../game/clientbound_update_tags_packet.rs | 32 +- ...clientbound_update_view_distance_packet.rs | 2 - .../game/serverbound_custom_payload_packet.rs | 2 - .../handshake/client_intention_packet.rs | 24 +- .../login/clientbound_game_profile_packet.rs | 16 +- .../packets/login/clientbound_hello_packet.rs | 12 +- .../clientbound_login_compression_packet.rs | 8 +- azalea-protocol/src/packets/mod.rs | 21 +- .../clientbound_status_response_packet.rs | 8 +- azalea-protocol/src/read.rs | 56 +-- 29 files changed, 469 insertions(+), 781 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 254dc5db..e15fd564 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.3.8" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443ccbb270374a2b1055fc72da40e1f237809cd6bb0e97e66d264cd138473a6" +checksum = "f2bf394cfbbe876f0ac67b13b6ca819f9c9f2fb9ec67223cceb1555fbab1c31a" dependencies = [ "flate2", "futures-core", @@ -127,14 +127,11 @@ dependencies = [ name = "azalea-nbt" version = "0.1.0" dependencies = [ - "async-compression", - "async-recursion", "byteorder", "criterion", "flate2", "num-derive", "num-traits", - "tokio", ] [[package]] @@ -143,7 +140,6 @@ version = "0.1.0" dependencies = [ "async-compression", "async-recursion", - "async-trait", "azalea-auth", "azalea-brigadier", "azalea-chat", @@ -152,6 +148,7 @@ dependencies = [ "azalea-nbt", "byteorder", "bytes", + "flate2", "num-derive", "num-traits", "packet-macros", @@ -302,7 +299,6 @@ dependencies = [ "clap", "criterion-plot", "csv", - "futures", "itertools", "lazy_static", "num-traits", @@ -315,7 +311,6 @@ dependencies = [ "serde_derive", "serde_json", "tinytemplate", - "tokio", "walkdir", ] @@ -441,9 +436,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ "cfg-if", "crc32fast", @@ -461,20 +456,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.18" @@ -482,7 +463,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -516,7 +496,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" dependencies = [ "futures-core", - "futures-sink", "futures-task", "pin-project-lite", "pin-utils", @@ -725,12 +704,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg", ] [[package]] diff --git a/azalea-client/src/connect.rs b/azalea-client/src/connect.rs index 826bce3d..9d623215 100755 --- a/azalea-client/src/connect.rs +++ b/azalea-client/src/connect.rs @@ -135,7 +135,7 @@ impl Client { let game_loop_conn = conn.clone(); let game_loop_state = client.state.clone(); - tokio::spawn(async move { Self::game_loop(game_loop_conn, tx, game_loop_state).await }); + tokio::spawn(Self::game_loop(game_loop_conn, tx, game_loop_state)); Ok(client) } diff --git a/azalea-nbt/Cargo.toml b/azalea-nbt/Cargo.toml index d4817233..ad466e1f 100755 --- a/azalea-nbt/Cargo.toml +++ b/azalea-nbt/Cargo.toml @@ -6,17 +6,13 @@ version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-compression = {version = "^0.3.8", features = ["tokio", "zlib", "gzip"]} -async-recursion = "^0.3.2" -byteorder = "^1.4.3" -flate2 = "^1.0.22" +byteorder = "1.4.3" +flate2 = "1.0.23" num-derive = "^0.3.3" num-traits = "^0.2.14" -tokio = "^1.15.0" [dev-dependencies] -criterion = {version = "^0.3.5", features = ["html_reports", "async_tokio"]} -tokio = {version = "^1.15.0", features = ["fs", "io-util", "macros", "rt", "rt-multi-thread"]} +criterion = {version = "^0.3.5", features = ["html_reports"]} [profile.release] lto = true diff --git a/azalea-nbt/benches/my_benchmark.rs b/azalea-nbt/benches/my_benchmark.rs index 2fc7ec2f..a6e68486 100755 --- a/azalea-nbt/benches/my_benchmark.rs +++ b/azalea-nbt/benches/my_benchmark.rs @@ -19,10 +19,7 @@ fn bench_serialize(filename: &str, c: &mut Criterion) { let mut decoded_src_stream = std::io::Cursor::new(decoded_src.clone()); file.seek(SeekFrom::Start(0)).unwrap(); - // run Tag::read(&mut decoded_src_stream) asynchronously - let nbt = tokio::runtime::Runtime::new() - .unwrap() - .block_on(async { Tag::read(&mut decoded_src_stream).await.unwrap() }); + let nbt = Tag::read(&mut decoded_src_stream).unwrap(); let mut group = c.benchmark_group(filename); diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs index 3e2f7adb..52f1c97e 100755 --- a/azalea-nbt/src/decode.rs +++ b/azalea-nbt/src/decode.rs @@ -1,64 +1,63 @@ use crate::Error; use crate::Tag; -use async_compression::tokio::bufread::{GzipDecoder, ZlibDecoder}; -use async_recursion::async_recursion; +use byteorder::{ReadBytesExt, BE}; +use flate2::read::{GzDecoder, ZlibDecoder}; use std::collections::HashMap; -use tokio::io::AsyncBufRead; -use tokio::io::{AsyncRead, AsyncReadExt}; +use std::io::BufRead; +use std::io::Read; #[inline] -async fn read_string(stream: &mut R) -> Result +fn read_string(stream: &mut R) -> Result where - R: AsyncRead + std::marker::Unpin, + R: Read, { - let length = stream.read_u16().await?; + let length = stream.read_u16::()?; let mut buf = Vec::with_capacity(length as usize); for _ in 0..length { - buf.push(stream.read_u8().await?); + buf.push(stream.read_u8()?); } Ok(String::from_utf8(buf)?) } impl Tag { #[inline] - #[async_recursion] - async fn read_known(stream: &mut R, id: u8) -> Result + fn read_known(stream: &mut R, id: u8) -> Result where - R: AsyncRead + std::marker::Unpin + std::marker::Send, + R: Read, { let tag = match id { // Signifies the end of a TAG_Compound. It is only ever used inside // a TAG_Compound, and is not named despite being in a TAG_Compound 0 => Tag::End, // A single signed byte - 1 => Tag::Byte(stream.read_i8().await?), + 1 => Tag::Byte(stream.read_i8()?), // A single signed, big endian 16 bit integer - 2 => Tag::Short(stream.read_i16().await?), + 2 => Tag::Short(stream.read_i16::()?), // A single signed, big endian 32 bit integer - 3 => Tag::Int(stream.read_i32().await?), + 3 => Tag::Int(stream.read_i32::()?), // A single signed, big endian 64 bit integer - 4 => Tag::Long(stream.read_i64().await?), + 4 => Tag::Long(stream.read_i64::()?), // A single, big endian IEEE-754 single-precision floating point // number (NaN possible) - 5 => Tag::Float(stream.read_f32().await?), + 5 => Tag::Float(stream.read_f32::()?), // A single, big endian IEEE-754 double-precision floating point // number (NaN possible) - 6 => Tag::Double(stream.read_f64().await?), + 6 => Tag::Double(stream.read_f64::()?), // A length-prefixed array of signed bytes. The prefix is a signed // integer (thus 4 bytes) 7 => { - let length = stream.read_i32().await?; + let length = stream.read_i32::()?; let mut bytes = Vec::with_capacity(length as usize); for _ in 0..length { - bytes.push(stream.read_i8().await?); + bytes.push(stream.read_i8()?); } Tag::ByteArray(bytes) } // A length-prefixed modified UTF-8 string. The prefix is an // unsigned short (thus 2 bytes) signifying the length of the // string in bytes - 8 => Tag::String(read_string(stream).await?), + 8 => Tag::String(read_string(stream)?), // A list of nameless tags, all of the same type. The list is // prefixed with the Type ID of the items it contains (thus 1 // byte), and the length of the list as a signed integer (a further @@ -68,11 +67,11 @@ impl Tag { // another reference implementation by Mojang uses 1 instead; // parsers should accept any type if the length is <= 0). 9 => { - let type_id = stream.read_u8().await?; - let length = stream.read_i32().await?; + let type_id = stream.read_u8()?; + let length = stream.read_i32::()?; let mut list = Vec::with_capacity(length as usize); for _ in 0..length { - list.push(Tag::read_known(stream, type_id).await?); + list.push(Tag::read_known(stream, type_id)?); } Tag::List(list) } @@ -81,12 +80,12 @@ impl Tag { // we default to capacity 4 because it'll probably not be empty let mut map = HashMap::with_capacity(4); loop { - let tag_id = stream.read_u8().await.unwrap_or(0); + let tag_id = stream.read_u8().unwrap_or(0); if tag_id == 0 { break; } - let name = read_string(stream).await?; - let tag = Tag::read_known(stream, tag_id).await?; + let name = read_string(stream)?; + let tag = Tag::read_known(stream, tag_id)?; map.insert(name, tag); } Tag::Compound(map) @@ -95,20 +94,20 @@ impl Tag { // signed integer (thus 4 bytes) and indicates the number of 4 byte // integers. 11 => { - let length = stream.read_i32().await?; + let length = stream.read_i32::()?; let mut ints = Vec::with_capacity(length as usize); for _ in 0..length { - ints.push(stream.read_i32().await?); + ints.push(stream.read_i32::()?); } Tag::IntArray(ints) } // A length-prefixed array of signed longs. The prefix is a signed // integer (thus 4 bytes) and indicates the number of 8 byte longs. 12 => { - let length = stream.read_i32().await?; + let length = stream.read_i32::()?; let mut longs = Vec::with_capacity(length as usize); for _ in 0..length { - longs.push(stream.read_i64().await?); + longs.push(stream.read_i64::()?); } Tag::LongArray(longs) } @@ -117,38 +116,38 @@ impl Tag { Ok(tag) } - pub async fn read(stream: &mut R) -> Result + pub fn read(stream: &mut R) -> Result where - R: AsyncRead + std::marker::Unpin + std::marker::Send, + R: Read, { // default to compound tag // the parent compound only ever has one item - let tag_id = stream.read_u8().await.unwrap_or(0); + let tag_id = stream.read_u8().unwrap_or(0); if tag_id == 0 { return Ok(Tag::End); } - let name = read_string(stream).await?; - let tag = Tag::read_known(stream, tag_id).await?; + let name = read_string(stream)?; + let tag = Tag::read_known(stream, tag_id)?; let mut map = HashMap::with_capacity(1); map.insert(name, tag); Ok(Tag::Compound(map)) } - pub async fn read_zlib(stream: &mut R) -> Result + pub fn read_zlib(stream: &mut R) -> Result where - R: AsyncBufRead + std::marker::Unpin + std::marker::Send, + R: BufRead, { let mut gz = ZlibDecoder::new(stream); - Tag::read(&mut gz).await + Tag::read(&mut gz) } - pub async fn read_gzip(stream: &mut R) -> Result + pub fn read_gzip(stream: &mut R) -> Result where - R: AsyncBufRead + std::marker::Unpin + std::marker::Send, + R: Read, { - let mut gz = GzipDecoder::new(stream); - Tag::read(&mut gz).await + let mut gz = GzDecoder::new(stream); + Tag::read(&mut gz) } } diff --git a/azalea-nbt/tests/tests.rs b/azalea-nbt/tests/tests.rs index 75b3a646..7f20e54d 100755 --- a/azalea-nbt/tests/tests.rs +++ b/azalea-nbt/tests/tests.rs @@ -1,15 +1,15 @@ use azalea_nbt::Tag; use std::{ collections::HashMap, + fs::File, io::{Cursor, Read}, }; -use tokio::{fs::File, io::AsyncReadExt}; -#[tokio::test] -async fn test_decode_hello_world() { +#[test] +fn test_decode_hello_world() { // read hello_world.nbt - let mut file = File::open("tests/hello_world.nbt").await.unwrap(); - let tag = Tag::read(&mut file).await.unwrap(); + let mut file = File::open("tests/hello_world.nbt").unwrap(); + let tag = Tag::read(&mut file).unwrap(); assert_eq!( tag, Tag::Compound(HashMap::from_iter(vec![( @@ -22,14 +22,14 @@ async fn test_decode_hello_world() { ); } -#[tokio::test] -async fn test_roundtrip_hello_world() { - let mut file = File::open("tests/hello_world.nbt").await.unwrap(); +#[test] +fn test_roundtrip_hello_world() { + let mut file = File::open("tests/hello_world.nbt").unwrap(); let mut original = Vec::new(); - file.read_to_end(&mut original).await.unwrap(); + file.read_to_end(&mut original).unwrap(); let mut original_stream = Cursor::new(original.clone()); - let tag = Tag::read(&mut original_stream).await.unwrap(); + let tag = Tag::read(&mut original_stream).unwrap(); // write hello_world.nbt let mut result = Cursor::new(Vec::new()); @@ -38,26 +38,26 @@ async fn test_roundtrip_hello_world() { assert_eq!(result.into_inner(), original); } -#[tokio::test] -async fn test_bigtest() { +#[test] +fn test_bigtest() { // read bigtest.nbt - let mut file = File::open("tests/bigtest.nbt").await.unwrap(); + let mut file = File::open("tests/bigtest.nbt").unwrap(); let mut original = Vec::new(); - file.read_to_end(&mut original).await.unwrap(); + file.read_to_end(&mut original).unwrap(); let mut original_stream = Cursor::new(original.clone()); - let original_tag = Tag::read_gzip(&mut original_stream).await.unwrap(); + let original_tag = Tag::read_gzip(&mut original_stream).unwrap(); let mut result = Vec::new(); original_tag.write(&mut result).unwrap(); - let decoded_tag = Tag::read(&mut Cursor::new(result)).await.unwrap(); + let decoded_tag = Tag::read(&mut Cursor::new(result)).unwrap(); assert_eq!(decoded_tag, original_tag); } -#[tokio::test] -async fn test_stringtest() { +#[test] +fn test_stringtest() { let correct_tag = Tag::Compound(HashMap::from_iter(vec![( "😃".to_string(), Tag::List(vec![ @@ -84,41 +84,41 @@ async fn test_stringtest() { file.read_to_end(&mut original).unwrap(); let mut original_stream = Cursor::new(original.clone()); - let original_tag = Tag::read_gzip(&mut original_stream).await.unwrap(); + let original_tag = Tag::read_gzip(&mut original_stream).unwrap(); assert_eq!(original_tag, correct_tag); } -#[tokio::test] -async fn test_complex_player() { - let mut file = File::open("tests/complex_player.dat").await.unwrap(); +#[test] +fn test_complex_player() { + let mut file = File::open("tests/complex_player.dat").unwrap(); let mut original = Vec::new(); - file.read_to_end(&mut original).await.unwrap(); + file.read_to_end(&mut original).unwrap(); let mut original_stream = Cursor::new(original.clone()); - let original_tag = Tag::read_gzip(&mut original_stream).await.unwrap(); + let original_tag = Tag::read_gzip(&mut original_stream).unwrap(); let mut result = Vec::new(); original_tag.write(&mut result).unwrap(); - let decoded_tag = Tag::read(&mut Cursor::new(result)).await.unwrap(); + let decoded_tag = Tag::read(&mut Cursor::new(result)).unwrap(); assert_eq!(decoded_tag, original_tag); } -#[tokio::test] -async fn test_simple_player() { - let mut file = File::open("tests/simple_player.dat").await.unwrap(); +#[test] +fn test_simple_player() { + let mut file = File::open("tests/simple_player.dat").unwrap(); let mut original = Vec::new(); - file.read_to_end(&mut original).await.unwrap(); + file.read_to_end(&mut original).unwrap(); let mut original_stream = Cursor::new(original.clone()); - let original_tag = Tag::read_gzip(&mut original_stream).await.unwrap(); + let original_tag = Tag::read_gzip(&mut original_stream).unwrap(); let mut result = Vec::new(); original_tag.write(&mut result).unwrap(); - let decoded_tag = Tag::read(&mut Cursor::new(result)).await.unwrap(); + let decoded_tag = Tag::read(&mut Cursor::new(result)).unwrap(); assert_eq!(decoded_tag, original_tag); } diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml index 9ebcd9d7..899b44a8 100755 --- a/azalea-protocol/Cargo.toml +++ b/azalea-protocol/Cargo.toml @@ -8,7 +8,6 @@ version = "0.1.0" [dependencies] async-compression = {version = "^0.3.8", features = ["tokio", "zlib"]} async-recursion = "^0.3.2" -async-trait = "0.1.51" azalea-auth = {path = "../azalea-auth"} azalea-brigadier = {path = "../azalea-brigadier"} azalea-chat = {path = "../azalea-chat"} @@ -17,6 +16,7 @@ azalea-crypto = {path = "../azalea-crypto"} azalea-nbt = {path = "../azalea-nbt"} byteorder = "^1.4.3" bytes = "^1.1.0" +flate2 = "1.0.23" num-derive = "^0.3.3" num-traits = "^0.2.14" packet-macros = {path = "./packet-macros"} diff --git a/azalea-protocol/packet-macros/src/lib.rs b/azalea-protocol/packet-macros/src/lib.rs index 6c1998b9..0d912257 100755 --- a/azalea-protocol/packet-macros/src/lib.rs +++ b/azalea-protocol/packet-macros/src/lib.rs @@ -25,11 +25,11 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt syn::Type::Path(_) => { if f.attrs.iter().any(|a| a.path.is_ident("varint")) { quote! { - let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf).await?; + let #field_name = crate::mc_buf::McBufVarintReadable::varint_read_into(buf)?; } } else { quote! { - let #field_name = crate::mc_buf::McBufReadable::read_into(buf).await?; + let #field_name = crate::mc_buf::McBufReadable::read_into(buf)?; } } } @@ -44,12 +44,8 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt let read_field_names = named.iter().map(|f| &f.ident).collect::>(); quote! { - #[async_trait::async_trait] impl crate::mc_buf::McBufReadable for #ident { - async fn read_into(buf: &mut R) -> Result - where - R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send, - { + fn read_into(buf: &mut impl std::io::Read) -> Result { #(#read_fields)* Ok(#ident { #(#read_field_names: #read_field_names),* @@ -73,13 +69,10 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt } quote! { - #[async_trait::async_trait] impl crate::mc_buf::McBufReadable for #ident { - async fn read_into(buf: &mut R) -> Result - where - R: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send, + fn read_into(buf: &mut impl std::io::Read) -> Result { - let id = buf.read_varint().await?; + let id = buf.read_varint()?; match id { #match_contents _ => Err(format!("Unknown enum variant {}", id)), @@ -189,11 +182,11 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke crate::mc_buf::McBufWritable::write_into(self, buf) } - pub async fn read( - buf: &mut T, + pub fn read( + buf: &mut impl std::io::Read, ) -> Result<#state, String> { use crate::mc_buf::McBufReadable; - Ok(Self::read_into(buf).await?.get()) + Ok(Self::read_into(buf)?.get()) } } @@ -339,7 +332,7 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream { #state_name::#name(packet) => packet.write(buf), }); serverbound_read_match_contents.extend(quote! { - #id => #module::#name::read(buf).await?, + #id => #module::#name::read(buf)?, }); } for PacketIdPair { id, module, name } in input.clientbound.packets { @@ -353,7 +346,7 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream { #state_name::#name(packet) => packet.write(buf), }); clientbound_read_match_contents.extend(quote! { - #id => #module::#name::read(buf).await?, + #id => #module::#name::read(buf)?, }); } @@ -366,7 +359,6 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream { #enum_contents } - #[async_trait::async_trait] impl crate::packets::ProtocolPacket for #state_name { fn id(&self) -> u32 { match self { @@ -381,10 +373,10 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream { } /// Read a packet by its id, ConnectionProtocol, and flow - async fn read( + fn read( id: u32, flow: &crate::connect::PacketFlow, - buf: &mut T, + buf: &mut impl std::io::Read, ) -> Result<#state_name, String> where Self: Sized, diff --git a/azalea-protocol/src/mc_buf/mod.rs b/azalea-protocol/src/mc_buf/mod.rs index d50817fb..a61ad3c3 100755 --- a/azalea-protocol/src/mc_buf/mod.rs +++ b/azalea-protocol/src/mc_buf/mod.rs @@ -4,7 +4,7 @@ mod read; mod write; use packet_macros::{McBufReadable, McBufWritable}; -pub use read::{McBufReadable, McBufVarintReadable, Readable}; +pub use read::{read_varint_async, McBufReadable, McBufVarintReadable, Readable}; use std::ops::{Deref, Index}; pub use write::{McBufVarintWritable, McBufWritable, Writable}; @@ -56,7 +56,6 @@ mod tests { use super::*; use azalea_core::resource_location::ResourceLocation; use std::{collections::HashMap, io::Cursor}; - use tokio::io::BufReader; #[test] fn test_write_varint() { @@ -105,91 +104,91 @@ mod tests { assert_eq!(buf, vec![128, 128, 128, 128, 8]); } - #[tokio::test] - async fn test_read_varint() { - let mut buf = BufReader::new(Cursor::new(vec![0])); - assert_eq!(buf.read_varint().await.unwrap(), 0); + #[test] + fn test_read_varint() { + let mut buf = Cursor::new(vec![0]); + assert_eq!(buf.read_varint().unwrap(), 0); assert_eq!(buf.get_varint_size(0), 1); - let mut buf = BufReader::new(Cursor::new(vec![1])); - assert_eq!(buf.read_varint().await.unwrap(), 1); + let mut buf = Cursor::new(vec![1]); + assert_eq!(buf.read_varint().unwrap(), 1); assert_eq!(buf.get_varint_size(1), 1); - let mut buf = BufReader::new(Cursor::new(vec![2])); - assert_eq!(buf.read_varint().await.unwrap(), 2); + let mut buf = Cursor::new(vec![2]); + assert_eq!(buf.read_varint().unwrap(), 2); assert_eq!(buf.get_varint_size(2), 1); - let mut buf = BufReader::new(Cursor::new(vec![127])); - assert_eq!(buf.read_varint().await.unwrap(), 127); + let mut buf = Cursor::new(vec![127]); + assert_eq!(buf.read_varint().unwrap(), 127); assert_eq!(buf.get_varint_size(127), 1); - let mut buf = BufReader::new(Cursor::new(vec![128, 1])); - assert_eq!(buf.read_varint().await.unwrap(), 128); + let mut buf = Cursor::new(vec![128, 1]); + assert_eq!(buf.read_varint().unwrap(), 128); assert_eq!(buf.get_varint_size(128), 2); - let mut buf = BufReader::new(Cursor::new(vec![255, 1])); - assert_eq!(buf.read_varint().await.unwrap(), 255); + let mut buf = Cursor::new(vec![255, 1]); + assert_eq!(buf.read_varint().unwrap(), 255); assert_eq!(buf.get_varint_size(255), 2); - let mut buf = BufReader::new(Cursor::new(vec![221, 199, 1])); - assert_eq!(buf.read_varint().await.unwrap(), 25565); + let mut buf = Cursor::new(vec![221, 199, 1]); + assert_eq!(buf.read_varint().unwrap(), 25565); assert_eq!(buf.get_varint_size(25565), 3); - let mut buf = BufReader::new(Cursor::new(vec![255, 255, 127])); - assert_eq!(buf.read_varint().await.unwrap(), 2097151); + let mut buf = Cursor::new(vec![255, 255, 127]); + assert_eq!(buf.read_varint().unwrap(), 2097151); assert_eq!(buf.get_varint_size(2097151), 3); - let mut buf = BufReader::new(Cursor::new(vec![255, 255, 255, 255, 7])); - assert_eq!(buf.read_varint().await.unwrap(), 2147483647); + let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]); + assert_eq!(buf.read_varint().unwrap(), 2147483647); assert_eq!(buf.get_varint_size(2147483647), 5); - let mut buf = BufReader::new(Cursor::new(vec![255, 255, 255, 255, 15])); - assert_eq!(buf.read_varint().await.unwrap(), -1); + let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]); + assert_eq!(buf.read_varint().unwrap(), -1); assert_eq!(buf.get_varint_size(-1), 5); - let mut buf = BufReader::new(Cursor::new(vec![128, 128, 128, 128, 8])); - assert_eq!(buf.read_varint().await.unwrap(), -2147483648); + let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]); + assert_eq!(buf.read_varint().unwrap(), -2147483648); assert_eq!(buf.get_varint_size(-2147483648), 5); } - #[tokio::test] - async fn test_read_varint_longer() { - let mut buf = BufReader::new(Cursor::new(vec![138, 56, 0, 135, 56, 123])); - assert_eq!(buf.read_varint().await.unwrap(), 7178); + #[test] + fn test_read_varint_longer() { + let mut buf = Cursor::new(vec![138, 56, 0, 135, 56, 123]); + assert_eq!(buf.read_varint().unwrap(), 7178); } - #[tokio::test] - async fn test_list() { + #[test] + fn test_list() { let mut buf = Vec::new(); buf.write_list(&vec!["a", "bc", "def"], |buf, s| buf.write_utf(s)) .unwrap(); // there's no read_list because idk how to do it in rust - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); let mut result = Vec::new(); - let length = buf.read_varint().await.unwrap(); + let length = buf.read_varint().unwrap(); for _ in 0..length { - result.push(buf.read_utf().await.unwrap()); + result.push(buf.read_utf().unwrap()); } assert_eq!(result, vec!["a", "bc", "def"]); } - #[tokio::test] - async fn test_int_id_list() { + #[test] + fn test_int_id_list() { let mut buf = Vec::new(); buf.write_list(&vec![1, 2, 3], |buf, i| buf.write_varint(*i)) .unwrap(); - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); - let result = buf.read_int_id_list().await.unwrap(); + let result = buf.read_int_id_list().unwrap(); assert_eq!(result, vec![1, 2, 3]); } - #[tokio::test] - async fn test_map() { + #[test] + fn test_map() { let mut buf = Vec::new(); buf.write_map( vec![("a", 1), ("bc", 23), ("def", 456)], @@ -198,15 +197,12 @@ mod tests { ) .unwrap(); - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); let mut result = Vec::new(); - let length = buf.read_varint().await.unwrap(); + let length = buf.read_varint().unwrap(); for _ in 0..length { - result.push(( - buf.read_utf().await.unwrap(), - buf.read_varint().await.unwrap(), - )); + result.push((buf.read_utf().unwrap(), buf.read_varint().unwrap())); } assert_eq!( @@ -219,8 +215,8 @@ mod tests { ); } - #[tokio::test] - async fn test_nbt() { + #[test] + fn test_nbt() { let mut buf = Vec::new(); buf.write_nbt(&azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( "hello world".to_string(), @@ -231,9 +227,9 @@ mod tests { )]))) .unwrap(); - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); - let result = buf.read_nbt().await.unwrap(); + let result = buf.read_nbt().unwrap(); assert_eq!( result, azalea_nbt::Tag::Compound(HashMap::from_iter(vec![( @@ -246,26 +242,26 @@ mod tests { ); } - #[tokio::test] - async fn test_long() { + #[test] + fn test_long() { let mut buf = Vec::new(); buf.write_long(123456).unwrap(); - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); - assert_eq!(buf.read_long().await.unwrap(), 123456); + assert_eq!(buf.read_long().unwrap(), 123456); } - #[tokio::test] - async fn test_resource_location() { + #[test] + fn test_resource_location() { let mut buf = Vec::new(); buf.write_resource_location(&ResourceLocation::new("minecraft:dirt").unwrap()) .unwrap(); - let mut buf = BufReader::new(Cursor::new(buf)); + let mut buf = Cursor::new(buf); assert_eq!( - buf.read_resource_location().await.unwrap(), + buf.read_resource_location().unwrap(), ResourceLocation::new("minecraft:dirt").unwrap() ); } diff --git a/azalea-protocol/src/mc_buf/read.rs b/azalea-protocol/src/mc_buf/read.rs index 53c137b3..68c9cb3f 100755 --- a/azalea-protocol/src/mc_buf/read.rs +++ b/azalea-protocol/src/mc_buf/read.rs @@ -1,60 +1,57 @@ -use async_trait::async_trait; +use super::{BitSet, UnsizedByteArray, MAX_STRING_LENGTH}; use azalea_chat::component::Component; use azalea_core::{ difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, serializable_uuid::SerializableUuid, BlockPos, Direction, Slot, SlotData, }; +use byteorder::{ReadBytesExt, WriteBytesExt, BE}; use serde::Deserialize; +use std::io::Read; use tokio::io::{AsyncRead, AsyncReadExt}; use uuid::Uuid; -use super::{BitSet, UnsizedByteArray, MAX_STRING_LENGTH}; - -#[async_trait] pub trait Readable { - async fn read_int_id_list(&mut self) -> Result, String>; - async fn read_varint(&mut self) -> Result; + fn read_int_id_list(&mut self) -> Result, String>; + fn read_varint(&mut self) -> Result; fn get_varint_size(&mut self, value: i32) -> u8; fn get_varlong_size(&mut self, value: i32) -> u8; - async fn read_byte_array(&mut self) -> Result, String>; - async fn read_bytes_with_len(&mut self, n: usize) -> Result, String>; - async fn read_bytes(&mut self) -> Result, String>; - async fn read_utf(&mut self) -> Result; - async fn read_utf_with_len(&mut self, max_length: u32) -> Result; - async fn read_byte(&mut self) -> Result; - async fn read_int(&mut self) -> Result; - async fn read_boolean(&mut self) -> Result; - async fn read_nbt(&mut self) -> Result; - async fn read_long(&mut self) -> Result; - async fn read_resource_location(&mut self) -> Result; - async fn read_short(&mut self) -> Result; - async fn read_float(&mut self) -> Result; - async fn read_double(&mut self) -> Result; - async fn read_uuid(&mut self) -> Result; + fn read_byte_array(&mut self) -> Result, String>; + fn read_bytes_with_len(&mut self, n: usize) -> Result, String>; + fn read_bytes(&mut self) -> Result, String>; + fn read_utf(&mut self) -> Result; + fn read_utf_with_len(&mut self, max_length: u32) -> Result; + fn read_byte(&mut self) -> Result; + fn read_int(&mut self) -> Result; + fn read_boolean(&mut self) -> Result; + fn read_nbt(&mut self) -> Result; + fn read_long(&mut self) -> Result; + fn read_resource_location(&mut self) -> Result; + fn read_short(&mut self) -> Result; + fn read_float(&mut self) -> Result; + fn read_double(&mut self) -> Result; + fn read_uuid(&mut self) -> Result; } -#[async_trait] impl Readable for R where - R: AsyncRead + std::marker::Unpin + std::marker::Send, + R: Read, { - async fn read_int_id_list(&mut self) -> Result, String> { - let len = self.read_varint().await?; + fn read_int_id_list(&mut self) -> Result, String> { + let len = self.read_varint()?; let mut list = Vec::with_capacity(len as usize); for _ in 0..len { - list.push(self.read_varint().await?); + list.push(self.read_varint()?); } Ok(list) } // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 /// Read a single varint from the reader and return the value, along with the number of bytes read - async fn read_varint(&mut self) -> Result { + fn read_varint(&mut self) -> Result { let mut buffer = [0]; let mut ans = 0; for i in 0..5 { self.read_exact(&mut buffer) - .await .map_err(|_| "Invalid VarInt".to_string())?; ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); if buffer[0] & 0b1000_0000 == 0 { @@ -84,34 +81,32 @@ where 10 } - async fn read_byte_array(&mut self) -> Result, String> { - let length = self.read_varint().await? as usize; - self.read_bytes_with_len(length).await + fn read_byte_array(&mut self) -> Result, String> { + let length = self.read_varint()? as usize; + self.read_bytes_with_len(length) } - async fn read_bytes_with_len(&mut self, n: usize) -> Result, String> { - let mut bytes = vec![0; n]; - match AsyncReadExt::read_exact(self, &mut bytes).await { - Ok(_) => Ok(bytes), - Err(_) => Err("Error reading bytes".to_string()), - } + fn read_bytes_with_len(&mut self, n: usize) -> Result, String> { + let mut buffer = vec![0; n]; + self.read_exact(&mut buffer) + .map_err(|_| "Error reading bytes".to_string())?; + Ok(buffer) } - async fn read_bytes(&mut self) -> Result, String> { + fn read_bytes(&mut self) -> Result, String> { // read to end of the buffer let mut bytes = vec![]; - AsyncReadExt::read_to_end(self, &mut bytes) - .await + self.read_to_end(&mut bytes) .map_err(|_| "Error reading bytes".to_string())?; Ok(bytes) } - async fn read_utf(&mut self) -> Result { - self.read_utf_with_len(MAX_STRING_LENGTH.into()).await + fn read_utf(&mut self) -> Result { + self.read_utf_with_len(MAX_STRING_LENGTH.into()) } - async fn read_utf_with_len(&mut self, max_length: u32) -> Result { - let length = self.read_varint().await?; + fn read_utf_with_len(&mut self, max_length: u32) -> Result { + let length = self.read_varint()?; // i don't know why it's multiplied by 4 but it's like that in mojang's code so if length < 0 { return Err( @@ -131,7 +126,6 @@ where let mut string = String::new(); let mut buffer = vec![0; length as usize]; self.read_exact(&mut buffer) - .await .map_err(|_| "Invalid UTF-8".to_string())?; string.push_str(std::str::from_utf8(&buffer).unwrap()); if string.len() > length as usize { @@ -145,342 +139,263 @@ where } /// Read a single byte from the reader - async fn read_byte(&mut self) -> Result { - match AsyncReadExt::read_u8(self).await { - Ok(r) => Ok(r), - Err(_) => Err("Error reading byte".to_string()), - } + fn read_byte(&mut self) -> Result { + self.read_u8().map_err(|_| "Error reading byte".to_string()) } - async fn read_int(&mut self) -> Result { - match AsyncReadExt::read_i32(self).await { + fn read_int(&mut self) -> Result { + match self.read_i32::() { Ok(r) => Ok(r), Err(_) => Err("Error reading int".to_string()), } } - async fn read_boolean(&mut self) -> Result { - match self.read_byte().await { - Ok(0) => Ok(false), - Ok(1) => Ok(true), + fn read_boolean(&mut self) -> Result { + match self.read_byte()? { + 0 => Ok(false), + 1 => Ok(true), _ => Err("Error reading boolean".to_string()), } } - async fn read_nbt(&mut self) -> Result { - match azalea_nbt::Tag::read(self).await { + fn read_nbt(&mut self) -> Result { + match azalea_nbt::Tag::read(self) { Ok(r) => Ok(r), // Err(e) => Err(e.to_string()), Err(e) => Err(e.to_string()).unwrap(), } } - async fn read_long(&mut self) -> Result { - match AsyncReadExt::read_i64(self).await { + fn read_long(&mut self) -> Result { + match self.read_i64::() { Ok(r) => Ok(r), Err(_) => Err("Error reading long".to_string()), } } - async fn read_resource_location(&mut self) -> Result { + fn read_resource_location(&mut self) -> Result { // get the resource location from the string - let location_string = self.read_utf().await?; + let location_string = self.read_utf()?; let location = ResourceLocation::new(&location_string)?; Ok(location) } - async fn read_short(&mut self) -> Result { - match AsyncReadExt::read_i16(self).await { + fn read_short(&mut self) -> Result { + match self.read_i16::() { Ok(r) => Ok(r), Err(_) => Err("Error reading short".to_string()), } } - async fn read_float(&mut self) -> Result { - match AsyncReadExt::read_f32(self).await { + fn read_float(&mut self) -> Result { + match self.read_f32::() { Ok(r) => Ok(r), Err(_) => Err("Error reading float".to_string()), } } - async fn read_double(&mut self) -> Result { - match AsyncReadExt::read_f64(self).await { + fn read_double(&mut self) -> Result { + match self.read_f64::() { Ok(r) => Ok(r), Err(_) => Err("Error reading double".to_string()), } } - async fn read_uuid(&mut self) -> Result { + fn read_uuid(&mut self) -> Result { Ok(Uuid::from_int_array([ - self.read_int().await? as u32, - self.read_int().await? as u32, - self.read_int().await? as u32, - self.read_int().await? as u32, + Readable::read_int(self)? as u32, + Readable::read_int(self)? as u32, + Readable::read_int(self)? as u32, + Readable::read_int(self)? as u32, ])) } } -#[async_trait] +// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 +/// Read a single varint from the reader and return the value, along with the number of bytes read +pub async fn read_varint_async(reader: &mut (dyn AsyncRead + Unpin + Send)) -> Result { + let mut buffer = [0]; + let mut ans = 0; + for i in 0..5 { + reader + .read_exact(&mut buffer) + .await + .map_err(|_| "Invalid VarInt".to_string())?; + ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); + if buffer[0] & 0b1000_0000 == 0 { + return Ok(ans); + } + } + Ok(ans) +} + pub trait McBufReadable where Self: Sized, { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send; + fn read_into(buf: &mut impl Read) -> Result; } -#[async_trait] pub trait McBufVarintReadable where Self: Sized, { - async fn varint_read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send; + fn varint_read_into(buf: &mut impl Read) -> Result; } -#[async_trait] impl McBufReadable for i32 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_int().await + fn read_into(buf: &mut impl Read) -> Result { + Readable::read_int(buf) } } -#[async_trait] impl McBufVarintReadable for i32 { - async fn varint_read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_varint().await + fn varint_read_into(buf: &mut impl Read) -> Result { + buf.read_varint() } } -#[async_trait] impl McBufReadable for UnsizedByteArray { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - Ok(UnsizedByteArray(buf.read_bytes().await?)) + fn read_into(buf: &mut impl Read) -> Result { + Ok(UnsizedByteArray(buf.read_bytes()?)) } } -#[async_trait] impl McBufReadable for Vec { - default async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let length = buf.read_varint().await? as usize; + default fn read_into(buf: &mut impl Read) -> Result { + let length = buf.read_varint()? as usize; let mut contents = Vec::with_capacity(length); for _ in 0..length { - contents.push(T::read_into(buf).await?); + contents.push(T::read_into(buf)?); } Ok(contents) } } -#[async_trait] impl McBufReadable for Vec { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_byte_array().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_byte_array() } } // string -#[async_trait] impl McBufReadable for String { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_utf().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_utf() } } // ResourceLocation -#[async_trait] impl McBufReadable for ResourceLocation { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_resource_location().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_resource_location() } } // u32 -#[async_trait] impl McBufReadable for u32 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_int().await.map(|i| i as u32) + fn read_into(buf: &mut impl Read) -> Result { + Readable::read_int(buf).map(|i| i as u32) } } // u32 varint -#[async_trait] impl McBufVarintReadable for u32 { - async fn varint_read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_varint().await.map(|i| i as u32) + fn varint_read_into(buf: &mut impl Read) -> Result { + buf.read_varint().map(|i| i as u32) } } // u16 -#[async_trait] impl McBufReadable for u16 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_short().await.map(|i| i as u16) + fn read_into(buf: &mut impl Read) -> Result { + buf.read_short().map(|i| i as u16) } } // i16 -#[async_trait] impl McBufReadable for i16 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_short().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_short() } } // u16 varint -#[async_trait] impl McBufVarintReadable for u16 { - async fn varint_read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_varint().await.map(|i| i as u16) + fn varint_read_into(buf: &mut impl Read) -> Result { + buf.read_varint().map(|i| i as u16) } } // i64 -#[async_trait] impl McBufReadable for i64 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_long().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_long() } } // u64 -#[async_trait] impl McBufReadable for u64 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - i64::read_into(buf).await.map(|i| i as u64) + fn read_into(buf: &mut impl Read) -> Result { + i64::read_into(buf).map(|i| i as u64) } } // bool -#[async_trait] impl McBufReadable for bool { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_boolean().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_boolean() } } // u8 -#[async_trait] impl McBufReadable for u8 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_byte().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_byte() } } // i8 -#[async_trait] impl McBufReadable for i8 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_byte().await.map(|i| i as i8) + fn read_into(buf: &mut impl Read) -> Result { + buf.read_byte().map(|i| i as i8) } } // f32 -#[async_trait] impl McBufReadable for f32 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_float().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_float() } } // f64 -#[async_trait] impl McBufReadable for f64 { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_double().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_double() } } // GameType -#[async_trait] impl McBufReadable for GameType { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - GameType::from_id(buf.read_byte().await?) + fn read_into(buf: &mut impl Read) -> Result { + GameType::from_id(buf.read_byte()?) } } // Option -#[async_trait] impl McBufReadable for Option { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - GameType::from_optional_id(buf.read_byte().await? as i8) + fn read_into(buf: &mut impl Read) -> Result { + GameType::from_optional_id(buf.read_byte()? as i8) } } // Option -#[async_trait] impl McBufReadable for Option { - default async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let present = buf.read_boolean().await?; + default fn read_into(buf: &mut impl Read) -> Result { + let present = buf.read_boolean()?; Ok(if present { - Some(T::read_into(buf).await?) + Some(T::read_into(buf)?) } else { None }) @@ -488,35 +403,23 @@ impl McBufReadable for Option { } // azalea_nbt::Tag -#[async_trait] impl McBufReadable for azalea_nbt::Tag { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_nbt().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_nbt() } } // Difficulty -#[async_trait] impl McBufReadable for Difficulty { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - Ok(Difficulty::by_id(u8::read_into(buf).await?)) + fn read_into(buf: &mut impl Read) -> Result { + Ok(Difficulty::by_id(u8::read_into(buf)?)) } } // Component -#[async_trait] impl McBufReadable for Component { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let string = buf.read_utf().await?; + fn read_into(buf: &mut impl Read) -> Result { + let string = buf.read_utf()?; let json: serde_json::Value = serde_json::from_str(string.as_str()) .map_err(|e| "Component isn't valid JSON".to_string())?; let component = Component::deserialize(json).map_err(|e| e.to_string())?; @@ -525,42 +428,30 @@ impl McBufReadable for Component { } // Slot -#[async_trait] impl McBufReadable for Slot { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let present = buf.read_boolean().await?; + fn read_into(buf: &mut impl Read) -> Result { + let present = buf.read_boolean()?; if !present { return Ok(Slot::Empty); } - let id = buf.read_varint().await?; - let count = buf.read_byte().await?; - let nbt = buf.read_nbt().await?; + let id = buf.read_varint()?; + let count = buf.read_byte()?; + let nbt = buf.read_nbt()?; Ok(Slot::Present(SlotData { id, count, nbt })) } } // Uuid -#[async_trait] impl McBufReadable for Uuid { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - buf.read_uuid().await + fn read_into(buf: &mut impl Read) -> Result { + buf.read_uuid() } } // BlockPos -#[async_trait] impl McBufReadable for BlockPos { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let val = u64::read_into(buf).await?; + fn read_into(buf: &mut impl Read) -> Result { + let val = u64::read_into(buf)?; let x = (val >> 38) as i32; let y = (val & 0xFFF) as i32; let z = ((val >> 12) & 0x3FFFFFF) as i32; @@ -569,13 +460,9 @@ impl McBufReadable for BlockPos { } // Direction -#[async_trait] impl McBufReadable for Direction { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - match buf.read_varint().await? { + fn read_into(buf: &mut impl Read) -> Result { + match buf.read_varint()? { 0 => Ok(Self::Down), 1 => Ok(Self::Up), 2 => Ok(Self::North), diff --git a/azalea-protocol/src/mc_buf/write.rs b/azalea-protocol/src/mc_buf/write.rs index e5437ae8..57ec3a48 100755 --- a/azalea-protocol/src/mc_buf/write.rs +++ b/azalea-protocol/src/mc_buf/write.rs @@ -1,5 +1,4 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH}; -use async_trait::async_trait; use azalea_chat::component::Component; use azalea_core::{ difficulty::Difficulty, game_type::GameType, resource_location::ResourceLocation, @@ -9,7 +8,6 @@ use byteorder::{BigEndian, WriteBytesExt}; use std::io::Write; use uuid::Uuid; -#[async_trait] pub trait Writable { fn write_list(&mut self, list: &[T], writer: F) -> Result<(), std::io::Error> where @@ -48,7 +46,6 @@ pub trait Writable { fn write_uuid(&mut self, uuid: &Uuid) -> Result<(), std::io::Error>; } -#[async_trait] impl Writable for Vec { fn write_list(&mut self, list: &[T], writer: F) -> Result<(), std::io::Error> where @@ -363,9 +360,8 @@ impl McBufWritable for Difficulty { } // Component -#[async_trait] impl McBufWritable for Component { - // async fn read_into(buf: &mut R) -> Result + // async fn read_into(buf: &mut impl Read) -> Result // where // R: AsyncRead + std::marker::Unpin + std::marker::Send, // { diff --git a/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs b/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs index afaa7fdd..703811c0 100755 --- a/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_declare_commands_packet.rs @@ -1,9 +1,7 @@ use super::GamePacket; use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; -use async_trait::async_trait; use azalea_core::resource_location::ResourceLocation; -use std::hash::Hash; -use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt}; +use std::{hash::Hash, io::Read}; #[derive(Hash, Clone, Debug)] pub struct ClientboundDeclareCommandsPacket { @@ -20,16 +18,14 @@ impl ClientboundDeclareCommandsPacket { panic!("ClientboundDeclareCommandsPacket::write not implemented") } - pub async fn read( - buf: &mut T, - ) -> Result { - let node_count = buf.read_varint().await?; + pub fn read(buf: &mut T) -> Result { + let node_count = buf.read_varint()?; let mut nodes = Vec::with_capacity(node_count as usize); for _ in 0..node_count { - let node = BrigadierNodeStub::read_into(buf).await?; + let node = BrigadierNodeStub::read_into(buf)?; nodes.push(node); } - let root_index = buf.read_varint().await?; + let root_index = buf.read_varint()?; Ok(GamePacket::ClientboundDeclareCommandsPacket( ClientboundDeclareCommandsPacket { entries: nodes, @@ -47,20 +43,16 @@ pub struct BrigadierNumber { min: Option, max: Option, } -#[async_trait] -impl McBufReadable for BrigadierNumber { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let flags = buf.read_byte().await?; +impl McBufReadable for BrigadierNumber { + fn read_into(buf: &mut impl Read) -> Result { + let flags = buf.read_byte()?; let min = if flags & 0x01 != 0 { - Some(T::read_into(buf).await?) + Some(T::read_into(buf)?) } else { None }; let max = if flags & 0x02 != 0 { - Some(T::read_into(buf).await?) + Some(T::read_into(buf)?) } else { None }; @@ -97,13 +89,9 @@ pub enum BrigadierString { GreedyPhrase = 2, } -#[async_trait] impl McBufReadable for BrigadierString { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let id = buf.read_byte().await?; + fn read_into(buf: &mut impl Read) -> Result { + let id = buf.read_byte()?; Ok(match id { 0 => BrigadierString::SingleWord, 1 => BrigadierString::QuotablePhrase, @@ -171,38 +159,24 @@ pub enum BrigadierParser { Resource { registry_key: ResourceLocation }, } -#[async_trait] impl McBufReadable for BrigadierParser { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let parser = buf.read_resource_location().await?; + fn read_into(buf: &mut impl Read) -> Result { + let parser = buf.read_resource_location()?; if parser == ResourceLocation::new("brigadier:bool")? { Ok(BrigadierParser::Bool) } else if parser == ResourceLocation::new("brigadier:double")? { - Ok(BrigadierParser::Double( - BrigadierNumber::read_into(buf).await?, - )) + Ok(BrigadierParser::Double(BrigadierNumber::read_into(buf)?)) } else if parser == ResourceLocation::new("brigadier:float")? { - Ok(BrigadierParser::Float( - BrigadierNumber::read_into(buf).await?, - )) + Ok(BrigadierParser::Float(BrigadierNumber::read_into(buf)?)) } else if parser == ResourceLocation::new("brigadier:integer")? { - Ok(BrigadierParser::Integer( - BrigadierNumber::read_into(buf).await?, - )) + Ok(BrigadierParser::Integer(BrigadierNumber::read_into(buf)?)) } else if parser == ResourceLocation::new("brigadier:long")? { - Ok(BrigadierParser::Long( - BrigadierNumber::read_into(buf).await?, - )) + Ok(BrigadierParser::Long(BrigadierNumber::read_into(buf)?)) } else if parser == ResourceLocation::new("brigadier:string")? { - Ok(BrigadierParser::String( - BrigadierString::read_into(buf).await?, - )) + Ok(BrigadierParser::String(BrigadierString::read_into(buf)?)) } else if parser == ResourceLocation::new("minecraft:entity")? { - let flags = buf.read_byte().await?; + let flags = buf.read_byte()?; Ok(BrigadierParser::Entity { single: flags & 0x01 != 0, players_only: flags & 0x02 != 0, @@ -250,7 +224,7 @@ impl McBufReadable for BrigadierParser { } else if parser == ResourceLocation::new("minecraft:scoreboard_slot")? { Ok(BrigadierParser::ScoreboardSlot) } else if parser == ResourceLocation::new("minecraft:score_holder")? { - let flags = buf.read_byte().await?; + let flags = buf.read_byte()?; Ok(BrigadierParser::ScoreHolder { allows_multiple: flags & 0x01 != 0, }) @@ -270,7 +244,7 @@ impl McBufReadable for BrigadierParser { Ok(BrigadierParser::EntityAnchor) } else if parser == ResourceLocation::new("minecraft:range")? { Ok(BrigadierParser::Range { - decimals_allowed: buf.read_boolean().await?, + decimals_allowed: buf.read_boolean()?, }) } else if parser == ResourceLocation::new("minecraft:int_range")? { Ok(BrigadierParser::IntRange) @@ -292,11 +266,11 @@ impl McBufReadable for BrigadierParser { Ok(BrigadierParser::Time) } else if parser == ResourceLocation::new("minecraft:resource_or_tag")? { Ok(BrigadierParser::ResourceOrTag { - registry_key: buf.read_resource_location().await?, + registry_key: buf.read_resource_location()?, }) } else if parser == ResourceLocation::new("minecraft:resource")? { Ok(BrigadierParser::Resource { - registry_key: buf.read_resource_location().await?, + registry_key: buf.read_resource_location()?, }) } else { panic!("Unknown Brigadier parser: {}", parser) @@ -305,13 +279,9 @@ impl McBufReadable for BrigadierParser { } // azalea_brigadier::tree::CommandNode -#[async_trait] impl McBufReadable for BrigadierNodeStub { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let flags = u8::read_into(buf).await?; + fn read_into(buf: &mut impl Read) -> Result { + let flags = u8::read_into(buf)?; if flags > 31 { println!( "Warning: The flags from a Brigadier node are over 31. This is probably a bug." @@ -323,21 +293,17 @@ impl McBufReadable for BrigadierNodeStub { let has_redirect = flags & 0x08 != 0; let has_suggestions_type = flags & 0x10 != 0; - let children = buf.read_int_id_list().await?; - let redirect_node = if has_redirect { - buf.read_varint().await? - } else { - 0 - }; + let children = buf.read_int_id_list()?; + let redirect_node = if has_redirect { buf.read_varint()? } else { 0 }; // argument node if node_type == 2 { - let name = buf.read_utf().await?; + let name = buf.read_utf()?; - let parser = BrigadierParser::read_into(buf).await?; + let parser = BrigadierParser::read_into(buf)?; let suggestions_type = if has_suggestions_type { - Some(buf.read_resource_location().await?) + Some(buf.read_resource_location()?) } else { None }; @@ -345,7 +311,7 @@ impl McBufReadable for BrigadierNodeStub { } // literal node if node_type == 1 { - let name = buf.read_utf().await?; + let name = buf.read_utf()?; return Ok(BrigadierNodeStub {}); } Ok(BrigadierNodeStub {}) diff --git a/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs index f4f528cf..3ca1ac85 100755 --- a/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_player_abilities_packet.rs @@ -1,9 +1,7 @@ -// i don't know the actual name of this packet, i couldn't find it in the source code +use std::io::Read; use crate::mc_buf::{McBufReadable, McBufWritable, Readable}; -use async_trait::async_trait; use packet_macros::GamePacket; -use tokio::io::AsyncRead; #[derive(Clone, Debug, GamePacket)] pub struct ClientboundPlayerAbilitiesPacket { @@ -21,13 +19,9 @@ pub struct PlayerAbilitiesFlags { pub instant_break: bool, } -#[async_trait] impl McBufReadable for PlayerAbilitiesFlags { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let byte = buf.read_byte().await?; + fn read_into(buf: &mut impl Read) -> Result { + let byte = buf.read_byte()?; Ok(PlayerAbilitiesFlags { invulnerable: byte & 1 != 0, flying: byte & 2 != 0, diff --git a/azalea-protocol/src/packets/game/clientbound_player_info_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_info_packet.rs index 3d4c3ac7..97b68259 100644 --- a/azalea-protocol/src/packets/game/clientbound_player_info_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_player_info_packet.rs @@ -1,10 +1,7 @@ -// i don't know the actual name of this packet, i couldn't find it in the source code - use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; -use async_trait::async_trait; use azalea_chat::component::Component; use packet_macros::{GamePacket, McBufReadable, McBufWritable}; -use tokio::io::AsyncRead; +use std::io::Read; use uuid::Uuid; #[derive(Clone, Debug, GamePacket)] @@ -64,19 +61,15 @@ pub struct RemovePlayer { uuid: Uuid, } -#[async_trait] impl McBufReadable for Action { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let id = buf.read_byte().await?; + fn read_into(buf: &mut impl Read) -> Result { + let id = buf.read_byte()?; Ok(match id { - 0 => Action::AddPlayer(Vec::::read_into(buf).await?), - 1 => Action::UpdateGameMode(Vec::::read_into(buf).await?), - 2 => Action::UpdateLatency(Vec::::read_into(buf).await?), - 3 => Action::UpdateDisplayName(Vec::::read_into(buf).await?), - 4 => Action::RemovePlayer(Vec::::read_into(buf).await?), + 0 => Action::AddPlayer(Vec::::read_into(buf)?), + 1 => Action::UpdateGameMode(Vec::::read_into(buf)?), + 2 => Action::UpdateLatency(Vec::::read_into(buf)?), + 3 => Action::UpdateDisplayName(Vec::::read_into(buf)?), + 4 => Action::RemovePlayer(Vec::::read_into(buf)?), _ => panic!("Unknown player info action id: {}", id), }) } diff --git a/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs index 5bb40d84..e47ca9e1 100644 --- a/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_player_position_packet.rs @@ -1,9 +1,7 @@ -// i don't know the actual name of this packet, i couldn't find it in the source code +use std::io::Read; use crate::mc_buf::{McBufReadable, McBufWritable, Readable}; -use async_trait::async_trait; use packet_macros::GamePacket; -use tokio::io::AsyncRead; #[derive(Clone, Debug, GamePacket)] pub struct ClientboundPlayerPositionPacket { @@ -29,13 +27,9 @@ pub struct RelativeArguments { pub x_rot: bool, } -#[async_trait] impl McBufReadable for RelativeArguments { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let byte = buf.read_byte().await?; + fn read_into(buf: &mut impl Read) -> Result { + let byte = buf.read_byte()?; Ok(RelativeArguments { x: byte & 0b1 != 0, y: byte & 0b10 != 0, diff --git a/azalea-protocol/src/packets/game/clientbound_recipe_packet.rs b/azalea-protocol/src/packets/game/clientbound_recipe_packet.rs index 69f26ddc..4847bbf8 100644 --- a/azalea-protocol/src/packets/game/clientbound_recipe_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_recipe_packet.rs @@ -1,8 +1,6 @@ -use async_trait::async_trait; -use azalea_chat::component::Component; use azalea_core::{resource_location::ResourceLocation, Slot}; use packet_macros::{GamePacket, McBufReadable, McBufWritable}; -use tokio::io::AsyncRead; +use std::io::Read; use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; @@ -42,13 +40,9 @@ impl McBufWritable for State { Ok(()) } } -#[async_trait] impl McBufReadable for State { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let state = buf.read_varint().await?.try_into().unwrap(); + fn read_into(buf: &mut impl Read) -> Result { + let state = buf.read_varint()?.try_into().unwrap(); Ok(match state { 0 => State::Init, 1 => State::Add, diff --git a/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs b/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs index 4cc456f3..302d832a 100644 --- a/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_set_entity_data_packet.rs @@ -1,12 +1,12 @@ +use std::io::Read; + use crate::{ mc_buf::{Readable, Writable}, packets::{McBufReadable, McBufWritable}, }; -use async_trait::async_trait; use azalea_chat::component::Component; use azalea_core::{BlockPos, Direction, Slot}; use packet_macros::{GamePacket, McBufReadable, McBufWritable}; -use tokio::io::AsyncRead; use uuid::Uuid; #[derive(Clone, Debug, GamePacket)] @@ -24,19 +24,15 @@ pub struct EntityDataItem { pub value: EntityDataValue, } -#[async_trait] impl McBufReadable for Vec { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { + fn read_into(buf: &mut impl Read) -> Result { let mut metadata = Vec::new(); loop { - let index = buf.read_byte().await?; + let index = buf.read_byte()?; if index == 0xff { break; } - let value = EntityDataValue::read_into(buf).await?; + let value = EntityDataValue::read_into(buf)?; metadata.push(EntityDataItem { index, value }); } Ok(metadata) @@ -81,51 +77,47 @@ pub enum EntityDataValue { Pose(Pose), } -#[async_trait] impl McBufReadable for EntityDataValue { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let type_ = buf.read_varint().await?; + fn read_into(buf: &mut impl Read) -> Result { + let type_ = buf.read_varint()?; Ok(match type_ { - 0 => EntityDataValue::Byte(buf.read_byte().await?), - 1 => EntityDataValue::Int(buf.read_varint().await?), - 2 => EntityDataValue::Float(buf.read_float().await?), - 3 => EntityDataValue::String(buf.read_utf().await?), - 4 => EntityDataValue::Component(Component::read_into(buf).await?), - 5 => EntityDataValue::OptionalComponent(Option::::read_into(buf).await?), - 6 => EntityDataValue::ItemStack(Slot::read_into(buf).await?), - 7 => EntityDataValue::Boolean(buf.read_boolean().await?), + 0 => EntityDataValue::Byte(buf.read_byte()?), + 1 => EntityDataValue::Int(buf.read_varint()?), + 2 => EntityDataValue::Float(buf.read_float()?), + 3 => EntityDataValue::String(buf.read_utf()?), + 4 => EntityDataValue::Component(Component::read_into(buf)?), + 5 => EntityDataValue::OptionalComponent(Option::::read_into(buf)?), + 6 => EntityDataValue::ItemStack(Slot::read_into(buf)?), + 7 => EntityDataValue::Boolean(buf.read_boolean()?), 8 => EntityDataValue::Rotations { - x: buf.read_float().await?, - y: buf.read_float().await?, - z: buf.read_float().await?, + x: buf.read_float()?, + y: buf.read_float()?, + z: buf.read_float()?, }, - 9 => EntityDataValue::BlockPos(BlockPos::read_into(buf).await?), - 10 => EntityDataValue::OptionalBlockPos(Option::::read_into(buf).await?), - 11 => EntityDataValue::Direction(Direction::read_into(buf).await?), - 12 => EntityDataValue::OptionalUuid(Option::::read_into(buf).await?), + 9 => EntityDataValue::BlockPos(BlockPos::read_into(buf)?), + 10 => EntityDataValue::OptionalBlockPos(Option::::read_into(buf)?), + 11 => EntityDataValue::Direction(Direction::read_into(buf)?), + 12 => EntityDataValue::OptionalUuid(Option::::read_into(buf)?), 13 => EntityDataValue::OptionalBlockState({ - let val = i32::read_into(buf).await?; + let val = i32::read_into(buf)?; if val == 0 { None } else { Some(val) } }), - 14 => EntityDataValue::CompoundTag(azalea_nbt::Tag::read_into(buf).await?), - 15 => EntityDataValue::Particle(Particle::read_into(buf).await?), - 16 => EntityDataValue::VillagerData(VillagerData::read_into(buf).await?), + 14 => EntityDataValue::CompoundTag(azalea_nbt::Tag::read_into(buf)?), + 15 => EntityDataValue::Particle(Particle::read_into(buf)?), + 16 => EntityDataValue::VillagerData(VillagerData::read_into(buf)?), 17 => EntityDataValue::OptionalUnsignedInt({ - let val = buf.read_varint().await?; + let val = buf.read_varint()?; if val == 0 { None } else { Some((val - 1) as u32) } }), - 18 => EntityDataValue::Pose(Pose::read_into(buf).await?), + 18 => EntityDataValue::Pose(Pose::read_into(buf)?), _ => return Err(format!("Unknown entity data type: {}", type_)), }) } @@ -309,18 +301,14 @@ pub struct VibrationParticle { pub ticks: u32, } -#[async_trait] impl McBufReadable for ParticleData { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let id = buf.read_varint().await?; + fn read_into(buf: &mut impl Read) -> Result { + let id = buf.read_varint()?; Ok(match id { 0 => ParticleData::AmbientEntityEffect, 1 => ParticleData::AngryVillager, - 2 => ParticleData::Block(BlockParticle::read_into(buf).await?), - 3 => ParticleData::BlockMarker(BlockParticle::read_into(buf).await?), + 2 => ParticleData::Block(BlockParticle::read_into(buf)?), + 3 => ParticleData::BlockMarker(BlockParticle::read_into(buf)?), 4 => ParticleData::Bubble, 5 => ParticleData::Cloud, 6 => ParticleData::Crit, @@ -331,10 +319,8 @@ impl McBufReadable for ParticleData { 11 => ParticleData::LandingLava, 12 => ParticleData::DrippingWater, 13 => ParticleData::FallingWater, - 14 => ParticleData::Dust(DustParticle::read_into(buf).await?), - 15 => ParticleData::DustColorTransition( - DustColorTransitionParticle::read_into(buf).await?, - ), + 14 => ParticleData::Dust(DustParticle::read_into(buf)?), + 15 => ParticleData::DustColorTransition(DustColorTransitionParticle::read_into(buf)?), 16 => ParticleData::Effect, 17 => ParticleData::ElderGuardian, 18 => ParticleData::EnchantedHit, @@ -343,7 +329,7 @@ impl McBufReadable for ParticleData { 21 => ParticleData::EntityEffect, 22 => ParticleData::ExplosionEmitter, 23 => ParticleData::Explosion, - 24 => ParticleData::FallingDust(BlockParticle::read_into(buf).await?), + 24 => ParticleData::FallingDust(BlockParticle::read_into(buf)?), 25 => ParticleData::Firework, 26 => ParticleData::Fishing, 27 => ParticleData::Flame, @@ -354,8 +340,8 @@ impl McBufReadable for ParticleData { 32 => ParticleData::Composter, 33 => ParticleData::Heart, 34 => ParticleData::InstantEffect, - 35 => ParticleData::Item(ItemParticle::read_into(buf).await?), - 36 => ParticleData::Vibration(VibrationParticle::read_into(buf).await?), + 35 => ParticleData::Item(ItemParticle::read_into(buf)?), + 36 => ParticleData::Vibration(VibrationParticle::read_into(buf)?), 37 => ParticleData::ItemSlime, 38 => ParticleData::ItemSnowball, 39 => ParticleData::LargeSmoke, diff --git a/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs index d7f86931..6e0aae29 100644 --- a/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_attributes_packet.rs @@ -1,10 +1,8 @@ -use async_trait::async_trait; -use azalea_core::{game_type::GameType, resource_location::ResourceLocation}; -use packet_macros::{GamePacket, McBufReadable, McBufWritable}; -use tokio::io::AsyncRead; -use uuid::Uuid; - use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; +use azalea_core::resource_location::ResourceLocation; +use packet_macros::{GamePacket, McBufReadable, McBufWritable}; +use std::io::Read; +use uuid::Uuid; #[derive(Clone, Debug, GamePacket)] pub struct ClientboundUpdateAttributesPacket { @@ -34,13 +32,9 @@ enum Operation { MultiplyTotal = 2, } -#[async_trait] impl McBufReadable for Operation { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - match buf.read_byte().await? { + fn read_into(buf: &mut impl Read) -> Result { + match buf.read_byte()? { 0 => Ok(Operation::Addition), 1 => Ok(Operation::MultiplyBase), 2 => Ok(Operation::MultiplyTotal), diff --git a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs index 5ae06a6f..4b1a322a 100644 --- a/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_recipes_packet.rs @@ -1,8 +1,7 @@ -use async_trait::async_trait; -use azalea_chat::component::Component; +use std::io::Read; + use azalea_core::{resource_location::ResourceLocation, Slot}; use packet_macros::{GamePacket, McBufReadable, McBufWritable}; -use tokio::io::AsyncRead; use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; @@ -48,20 +47,16 @@ impl McBufWritable for ShapedRecipe { Ok(()) } } -#[async_trait] impl McBufReadable for ShapedRecipe { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let width = buf.read_varint().await?.try_into().unwrap(); - let height = buf.read_varint().await?.try_into().unwrap(); - let group = buf.read_utf().await?; + fn read_into(buf: &mut impl Read) -> Result { + let width = buf.read_varint()?.try_into().unwrap(); + let height = buf.read_varint()?.try_into().unwrap(); + let group = buf.read_utf()?; let mut ingredients = Vec::with_capacity(width * height); for _ in 0..width * height { - ingredients.push(Ingredient::read_into(buf).await?); + ingredients.push(Ingredient::read_into(buf)?); } - let result = Slot::read_into(buf).await?; + let result = Slot::read_into(buf)?; Ok(ShapedRecipe { width, @@ -132,22 +127,18 @@ impl McBufWritable for Recipe { } } -#[async_trait] impl McBufReadable for Recipe { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let recipe_type = buf.read_resource_location().await?; - let identifier = buf.read_resource_location().await?; + fn read_into(buf: &mut impl Read) -> Result { + let recipe_type = buf.read_resource_location()?; + let identifier = buf.read_resource_location()?; // rust doesn't let us match ResourceLocation so we have to do a big // if-else chain :( let data = if recipe_type == ResourceLocation::new("minecraft:crafting_shapeless").unwrap() { - RecipeData::CraftingShapeless(ShapelessRecipe::read_into(buf).await?) + RecipeData::CraftingShapeless(ShapelessRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:crafting_shaped").unwrap() { - RecipeData::CraftingShaped(ShapedRecipe::read_into(buf).await?) + RecipeData::CraftingShaped(ShapedRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:crafting_special_armordye").unwrap() { @@ -205,17 +196,17 @@ impl McBufReadable for Recipe { { RecipeData::CraftingSpecialSuspiciousStew } else if recipe_type == ResourceLocation::new("minecraft:smelting").unwrap() { - RecipeData::Smelting(CookingRecipe::read_into(buf).await?) + RecipeData::Smelting(CookingRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:blasting").unwrap() { - RecipeData::Blasting(CookingRecipe::read_into(buf).await?) + RecipeData::Blasting(CookingRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:smoking").unwrap() { - RecipeData::Smoking(CookingRecipe::read_into(buf).await?) + RecipeData::Smoking(CookingRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:campfire_cooking").unwrap() { - RecipeData::CampfireCooking(CookingRecipe::read_into(buf).await?) + RecipeData::CampfireCooking(CookingRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:stonecutting").unwrap() { - RecipeData::Stonecutting(StoneCuttingRecipe::read_into(buf).await?) + RecipeData::Stonecutting(StoneCuttingRecipe::read_into(buf)?) } else if recipe_type == ResourceLocation::new("minecraft:smithing").unwrap() { - RecipeData::Smithing(SmithingRecipe::read_into(buf).await?) + RecipeData::Smithing(SmithingRecipe::read_into(buf)?) } else { panic!("Unknown recipe type sent by server: {}", recipe_type); }; diff --git a/azalea-protocol/src/packets/game/clientbound_update_tags_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_tags_packet.rs index b6046948..4646c2d3 100755 --- a/azalea-protocol/src/packets/game/clientbound_update_tags_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_tags_packet.rs @@ -1,11 +1,7 @@ -use std::collections::HashMap; - -use async_trait::async_trait; +use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; use azalea_core::resource_location::ResourceLocation; use packet_macros::GamePacket; -use tokio::io::AsyncRead; - -use crate::mc_buf::{McBufReadable, McBufWritable, Readable, Writable}; +use std::{collections::HashMap, io::Read}; #[derive(Clone, Debug, GamePacket)] pub struct ClientboundUpdateTagsPacket { @@ -18,20 +14,16 @@ pub struct Tags { pub elements: Vec, } -#[async_trait] impl McBufReadable for HashMap> { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let length = buf.read_varint().await? as usize; + fn read_into(buf: &mut impl Read) -> Result { + let length = buf.read_varint()? as usize; let mut data = HashMap::with_capacity(length); for _ in 0..length { - let tag_type = buf.read_resource_location().await?; - let tags_count = buf.read_varint().await? as usize; + let tag_type = buf.read_resource_location()?; + let tags_count = buf.read_varint()? as usize; let mut tags_vec = Vec::with_capacity(tags_count); for _ in 0..tags_count { - let tags = Tags::read_into(buf).await?; + let tags = Tags::read_into(buf)?; tags_vec.push(tags); } data.insert(tag_type, tags_vec); @@ -50,14 +42,10 @@ impl McBufWritable for HashMap> { Ok(()) } } -#[async_trait] impl McBufReadable for Tags { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - let name = buf.read_resource_location().await?; - let elements = buf.read_int_id_list().await?; + fn read_into(buf: &mut impl Read) -> Result { + let name = buf.read_resource_location()?; + let elements = buf.read_int_id_list()?; Ok(Tags { name, elements }) } } diff --git a/azalea-protocol/src/packets/game/clientbound_update_view_distance_packet.rs b/azalea-protocol/src/packets/game/clientbound_update_view_distance_packet.rs index 8301c089..1f988fe5 100755 --- a/azalea-protocol/src/packets/game/clientbound_update_view_distance_packet.rs +++ b/azalea-protocol/src/packets/game/clientbound_update_view_distance_packet.rs @@ -1,5 +1,3 @@ -// i don't know the actual name of this packet, i couldn't find it in the source code - use packet_macros::GamePacket; #[derive(Clone, Debug, GamePacket)] diff --git a/azalea-protocol/src/packets/game/serverbound_custom_payload_packet.rs b/azalea-protocol/src/packets/game/serverbound_custom_payload_packet.rs index 43ddb700..eefafdd1 100644 --- a/azalea-protocol/src/packets/game/serverbound_custom_payload_packet.rs +++ b/azalea-protocol/src/packets/game/serverbound_custom_payload_packet.rs @@ -1,5 +1,3 @@ -// i don't know the actual name of this packet, i couldn't find it in the source code - use crate::mc_buf::UnsizedByteArray; use azalea_core::resource_location::ResourceLocation; use packet_macros::GamePacket; diff --git a/azalea-protocol/src/packets/handshake/client_intention_packet.rs b/azalea-protocol/src/packets/handshake/client_intention_packet.rs index a92d65f6..6216ddc4 100755 --- a/azalea-protocol/src/packets/handshake/client_intention_packet.rs +++ b/azalea-protocol/src/packets/handshake/client_intention_packet.rs @@ -1,9 +1,7 @@ -use crate::{mc_buf::Writable, packets::ConnectionProtocol}; +use crate::packets::ConnectionProtocol; use packet_macros::HandshakePacket; use std::hash::Hash; -use super::HandshakePacket; - #[derive(Hash, Clone, Debug, HandshakePacket)] pub struct ClientIntentionPacket { #[varint] @@ -12,23 +10,3 @@ pub struct ClientIntentionPacket { pub port: u16, pub intention: ConnectionProtocol, } - -// impl ClientIntentionPacket { -// pub fn get(self) -> HandshakePacket { -// HandshakePacket::ClientIntentionPacket(self) -// } - -// pub fn write(&self, buf: &mut Vec) -> Result<(), std::io::Error> { -// buf.write_varint(self.protocol_version as i32)?; -// buf.write_utf(&self.hostname)?; -// buf.write_short(self.port as i16)?; -// buf.write_varint(self.intention as i32)?; -// Ok(()) -// } - -// pub async fn read( -// buf: &mut T, -// ) -> Result { -// todo!() -// } -// } diff --git a/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs b/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs index ccf0f482..bcdcd105 100755 --- a/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs +++ b/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs @@ -1,3 +1,5 @@ +use std::io::Read; + use super::LoginPacket; use crate::mc_buf::{Readable, Writable}; use azalea_auth::game_profile::GameProfile; @@ -23,17 +25,15 @@ impl ClientboundGameProfilePacket { Ok(()) } - pub async fn read( - buf: &mut T, - ) -> Result { + pub fn read(buf: &mut impl Read) -> Result { // TODO: we have a thing to read from the uuid now let uuid = Uuid::from_int_array([ - buf.read_int().await? as u32, - buf.read_int().await? as u32, - buf.read_int().await? as u32, - buf.read_int().await? as u32, + buf.read_int()? as u32, + buf.read_int()? as u32, + buf.read_int()? as u32, + buf.read_int()? as u32, ]); - let name = buf.read_utf_with_len(16).await?; + let name = buf.read_utf_with_len(16)?; Ok(ClientboundGameProfilePacket { game_profile: GameProfile::new(uuid, name), } diff --git a/azalea-protocol/src/packets/login/clientbound_hello_packet.rs b/azalea-protocol/src/packets/login/clientbound_hello_packet.rs index 20af1bec..06f346c2 100755 --- a/azalea-protocol/src/packets/login/clientbound_hello_packet.rs +++ b/azalea-protocol/src/packets/login/clientbound_hello_packet.rs @@ -1,4 +1,4 @@ -use std::hash::Hash; +use std::{hash::Hash, io::Read}; use super::LoginPacket; use crate::mc_buf::Readable; @@ -19,12 +19,10 @@ impl ClientboundHelloPacket { panic!("ClientboundHelloPacket::write not implemented") } - pub async fn read( - buf: &mut T, - ) -> Result { - let server_id = buf.read_utf_with_len(20).await?; - let public_key = buf.read_byte_array().await?; - let nonce = buf.read_byte_array().await?; + pub fn read(buf: &mut impl Read) -> Result { + let server_id = buf.read_utf_with_len(20)?; + let public_key = buf.read_byte_array()?; + let nonce = buf.read_byte_array()?; Ok(ClientboundHelloPacket { server_id, diff --git a/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs b/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs index a88c6cbf..a5ab78bb 100755 --- a/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs +++ b/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs @@ -1,4 +1,4 @@ -use std::hash::Hash; +use std::{hash::Hash, io::Read}; use crate::mc_buf::{Readable, Writable}; @@ -19,10 +19,8 @@ impl ClientboundLoginCompressionPacket { Ok(()) } - pub async fn read( - buf: &mut T, - ) -> Result { - let compression_threshold = buf.read_varint().await?; + pub fn read(buf: &mut impl Read) -> Result { + let compression_threshold = buf.read_varint()?; Ok(ClientboundLoginCompressionPacket { compression_threshold, diff --git a/azalea-protocol/src/packets/mod.rs b/azalea-protocol/src/packets/mod.rs index 98741a75..67fa92e9 100755 --- a/azalea-protocol/src/packets/mod.rs +++ b/azalea-protocol/src/packets/mod.rs @@ -3,14 +3,14 @@ pub mod handshake; pub mod login; pub mod status; +use std::io::Read; + use crate::{ connect::PacketFlow, mc_buf::{McBufReadable, McBufWritable, Readable, Writable}, }; -use async_trait::async_trait; use num_derive::FromPrimitive; use num_traits::FromPrimitive; -use tokio::io::AsyncRead; pub const PROTOCOL_VERSION: u32 = 758; @@ -31,7 +31,6 @@ pub enum Packet { } /// An enum of packets for a certain protocol -#[async_trait] pub trait ProtocolPacket where Self: Sized, @@ -39,24 +38,14 @@ where fn id(&self) -> u32; /// Read a packet by its id, ConnectionProtocol, and flow - async fn read( - id: u32, - flow: &PacketFlow, - buf: &mut T, - ) -> Result - where - Self: Sized; + fn read(id: u32, flow: &PacketFlow, buf: &mut impl Read) -> Result; fn write(&self, buf: &mut Vec) -> Result<(), std::io::Error>; } -#[async_trait] impl McBufReadable for ConnectionProtocol { - async fn read_into(buf: &mut R) -> Result - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { - ConnectionProtocol::from_i32(buf.read_varint().await?) + fn read_into(buf: &mut impl Read) -> Result { + ConnectionProtocol::from_i32(buf.read_varint()?) .ok_or_else(|| "Invalid intention".to_string()) } } diff --git a/azalea-protocol/src/packets/status/clientbound_status_response_packet.rs b/azalea-protocol/src/packets/status/clientbound_status_response_packet.rs index 884cf408..f5789ae3 100755 --- a/azalea-protocol/src/packets/status/clientbound_status_response_packet.rs +++ b/azalea-protocol/src/packets/status/clientbound_status_response_packet.rs @@ -1,3 +1,5 @@ +use std::io::Read; + use azalea_chat::component::Component; use serde::Deserialize; use serde_json::Value; @@ -43,10 +45,8 @@ impl ClientboundStatusResponsePacket { Ok(()) } - pub async fn read( - buf: &mut T, - ) -> Result { - let status_string = buf.read_utf().await?; + pub fn read(buf: &mut impl Read) -> Result { + let status_string = buf.read_utf()?; let status_json: Value = serde_json::from_str(status_string.as_str()).expect("Server status isn't valid JSON"); diff --git a/azalea-protocol/src/read.rs b/azalea-protocol/src/read.rs index 9afdb0e9..dd80bbc3 100755 --- a/azalea-protocol/src/read.rs +++ b/azalea-protocol/src/read.rs @@ -1,12 +1,16 @@ +use crate::{ + connect::PacketFlow, + mc_buf::{read_varint_async, Readable}, + packets::ProtocolPacket, +}; +use azalea_crypto::Aes128CfbDec; +use flate2::read::ZlibDecoder; use std::{ cell::Cell, + io::Read, pin::Pin, task::{Context, Poll}, }; - -use crate::{connect::PacketFlow, mc_buf::Readable, packets::ProtocolPacket}; -use async_compression::tokio::bufread::ZlibDecoder; -use azalea_crypto::Aes128CfbDec; use tokio::io::{AsyncRead, AsyncReadExt}; async fn frame_splitter(mut stream: &mut R) -> Result, String> @@ -14,7 +18,7 @@ where R: AsyncRead + std::marker::Unpin + std::marker::Send, { // Packet Length - let length_result = stream.read_varint().await; + let length_result = read_varint_async(&mut stream).await; match length_result { Ok(length) => { let mut buf = vec![0; length as usize]; @@ -30,16 +34,13 @@ where } } -async fn packet_decoder( - stream: &mut R, +fn packet_decoder( + stream: &mut impl Read, flow: &PacketFlow, -) -> Result -where - R: AsyncRead + std::marker::Unpin + std::marker::Send, -{ +) -> Result { // Packet ID - let packet_id = stream.read_varint().await?; - P::read(packet_id.try_into().unwrap(), flow, stream).await + let packet_id = stream.read_varint()?; + P::read(packet_id.try_into().unwrap(), flow, stream) } // this is always true in multiplayer, false in singleplayer @@ -47,22 +48,16 @@ static VALIDATE_DECOMPRESSED: bool = true; pub static MAXIMUM_UNCOMPRESSED_LENGTH: u32 = 2097152; -async fn compression_decoder( - stream: &mut R, +fn compression_decoder( + stream: &mut impl Read, compression_threshold: u32, -) -> Result, String> -where - R: AsyncRead + std::marker::Unpin + std::marker::Send, -{ +) -> Result, String> { // Data Length - let n: u32 = stream.read_varint().await?.try_into().unwrap(); + let n: u32 = stream.read_varint()?.try_into().unwrap(); if n == 0 { // no data size, no compression let mut buf = vec![]; - stream - .read_to_end(&mut buf) - .await - .map_err(|e| e.to_string())?; + stream.read_to_end(&mut buf).map_err(|e| e.to_string())?; return Ok(buf); } @@ -81,17 +76,10 @@ where } } - let mut buf = vec![]; - stream - .read_to_end(&mut buf) - .await - .map_err(|e| e.to_string())?; - let mut decoded_buf = vec![]; - let mut decoder = ZlibDecoder::new(buf.as_slice()); + let mut decoder = ZlibDecoder::new(stream); decoder .read_to_end(&mut decoded_buf) - .await .map_err(|e| e.to_string())?; Ok(decoded_buf) @@ -161,11 +149,11 @@ where // "decompressing packet ({}ms)", // start_time.elapsed().as_millis() // ); - buf = compression_decoder(&mut buf.as_slice(), compression_threshold).await?; + buf = compression_decoder(&mut &buf[..], compression_threshold)?; } // println!("decoding packet ({}ms)", start_time.elapsed().as_millis()); - let packet = packet_decoder(&mut buf.as_slice(), flow).await?; + let packet = packet_decoder(&mut buf.as_slice(), flow)?; // println!("decoded packet ({}ms)", start_time.elapsed().as_millis()); Ok(packet) From e1b6bc965a3f71d64b4dc3075da21c578ab5b508 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 1 May 2022 22:10:28 -0500 Subject: [PATCH 2/4] Update read.rs --- azalea-protocol/src/read.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azalea-protocol/src/read.rs b/azalea-protocol/src/read.rs index dd80bbc3..b4ba17ea 100755 --- a/azalea-protocol/src/read.rs +++ b/azalea-protocol/src/read.rs @@ -149,7 +149,7 @@ where // "decompressing packet ({}ms)", // start_time.elapsed().as_millis() // ); - buf = compression_decoder(&mut &buf[..], compression_threshold)?; + buf = compression_decoder(&mut buf.as_slice(), compression_threshold)?; } // println!("decoding packet ({}ms)", start_time.elapsed().as_millis()); From 44db8948d681df4245f3d93173667b10e58e046b Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 1 May 2022 22:53:24 -0500 Subject: [PATCH 3/4] Re-enable NBT decoding benchmark --- azalea-nbt/benches/my_benchmark.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/azalea-nbt/benches/my_benchmark.rs b/azalea-nbt/benches/my_benchmark.rs index a6e68486..ed963fb1 100755 --- a/azalea-nbt/benches/my_benchmark.rs +++ b/azalea-nbt/benches/my_benchmark.rs @@ -25,14 +25,13 @@ fn bench_serialize(filename: &str, c: &mut Criterion) { group.throughput(Throughput::Bytes(decoded_src.len() as u64)); - // group.bench_function("Decode", |b| { - // b.to_async(tokio::runtime::Runtime::new().unwrap()) - // .iter(|| async { - // let mut owned_decoded_src_stream = decoded_src_stream.clone(); - // owned_decoded_src_stream.seek(SeekFrom::Start(0)).unwrap(); - // Tag::read(&mut owned_decoded_src_stream).await.unwrap(); - // }) - // }); + group.bench_function("Decode", |b| { + b.iter(|| { + let mut owned_decoded_src_stream = decoded_src_stream.clone(); + owned_decoded_src_stream.seek(SeekFrom::Start(0)).unwrap(); + Tag::read(&mut owned_decoded_src_stream).unwrap(); + }) + }); group.bench_function("Encode", |b| { b.iter(|| { From db2fcecdc38ea7a43b098c6282dd906b73981f97 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 1 May 2022 22:58:20 -0500 Subject: [PATCH 4/4] Change some generics to impl Trait --- azalea-nbt/src/decode.rs | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs index 52f1c97e..7f2ca754 100755 --- a/azalea-nbt/src/decode.rs +++ b/azalea-nbt/src/decode.rs @@ -7,10 +7,7 @@ use std::io::BufRead; use std::io::Read; #[inline] -fn read_string(stream: &mut R) -> Result -where - R: Read, -{ +fn read_string(stream: &mut impl Read) -> Result { let length = stream.read_u16::()?; let mut buf = Vec::with_capacity(length as usize); @@ -22,10 +19,7 @@ where impl Tag { #[inline] - fn read_known(stream: &mut R, id: u8) -> Result - where - R: Read, - { + fn read_known(stream: &mut impl Read, id: u8) -> Result { let tag = match id { // Signifies the end of a TAG_Compound. It is only ever used inside // a TAG_Compound, and is not named despite being in a TAG_Compound @@ -116,10 +110,7 @@ impl Tag { Ok(tag) } - pub fn read(stream: &mut R) -> Result - where - R: Read, - { + pub fn read(stream: &mut impl Read) -> Result { // default to compound tag // the parent compound only ever has one item @@ -135,18 +126,12 @@ impl Tag { Ok(Tag::Compound(map)) } - pub fn read_zlib(stream: &mut R) -> Result - where - R: BufRead, - { + pub fn read_zlib(stream: &mut impl BufRead) -> Result { let mut gz = ZlibDecoder::new(stream); Tag::read(&mut gz) } - pub fn read_gzip(stream: &mut R) -> Result - where - R: Read, - { + pub fn read_gzip(stream: &mut impl Read) -> Result { let mut gz = GzDecoder::new(stream); Tag::read(&mut gz) }