diff options
| author | mat <github@matdoes.dev> | 2022-05-01 23:06:56 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-05-01 23:06:56 -0500 |
| commit | bec2da64d81883e3ea909452e71e17b9d22b2adc (patch) | |
| tree | d4f94abc09534768f2531a4c23f54dcc2dab2814 /azalea-nbt | |
| parent | 4d75415130a008f83c3bd594ca4cefd01f3d53dd (diff) | |
| parent | db2fcecdc38ea7a43b098c6282dd906b73981f97 (diff) | |
| download | azalea-drasl-bec2da64d81883e3ea909452e71e17b9d22b2adc.tar.xz | |
Merge branch 'main' into chunk-decoding
Diffstat (limited to 'azalea-nbt')
| -rwxr-xr-x | azalea-nbt/Cargo.toml | 10 | ||||
| -rwxr-xr-x | azalea-nbt/benches/my_benchmark.rs | 20 | ||||
| -rwxr-xr-x | azalea-nbt/src/decode.rs | 88 | ||||
| -rwxr-xr-x | azalea-nbt/tests/tests.rs | 62 |
4 files changed, 78 insertions, 102 deletions
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..ed963fb1 100755 --- a/azalea-nbt/benches/my_benchmark.rs +++ b/azalea-nbt/benches/my_benchmark.rs @@ -19,23 +19,19 @@ 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); 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(|| { diff --git a/azalea-nbt/src/decode.rs b/azalea-nbt/src/decode.rs index 3e2f7adb..7f2ca754 100755 --- a/azalea-nbt/src/decode.rs +++ b/azalea-nbt/src/decode.rs @@ -1,64 +1,57 @@ 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<R>(stream: &mut R) -> Result<String, Error> -where - R: AsyncRead + std::marker::Unpin, -{ - let length = stream.read_u16().await?; +fn read_string(stream: &mut impl Read) -> Result<String, Error> { + let length = stream.read_u16::<BE>()?; 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<R>(stream: &mut R, id: u8) -> Result<Tag, Error> - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { + fn read_known(stream: &mut impl Read, id: u8) -> Result<Tag, Error> { 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::<BE>()?), // A single signed, big endian 32 bit integer - 3 => Tag::Int(stream.read_i32().await?), + 3 => Tag::Int(stream.read_i32::<BE>()?), // A single signed, big endian 64 bit integer - 4 => Tag::Long(stream.read_i64().await?), + 4 => Tag::Long(stream.read_i64::<BE>()?), // 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::<BE>()?), // 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::<BE>()?), // 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::<BE>()?; 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 +61,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::<BE>()?; 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 +74,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 +88,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::<BE>()?; let mut ints = Vec::with_capacity(length as usize); for _ in 0..length { - ints.push(stream.read_i32().await?); + ints.push(stream.read_i32::<BE>()?); } 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::<BE>()?; let mut longs = Vec::with_capacity(length as usize); for _ in 0..length { - longs.push(stream.read_i64().await?); + longs.push(stream.read_i64::<BE>()?); } Tag::LongArray(longs) } @@ -117,38 +110,29 @@ impl Tag { Ok(tag) } - pub async fn read<R>(stream: &mut R) -> Result<Tag, Error> - where - R: AsyncRead + std::marker::Unpin + std::marker::Send, - { + pub fn read(stream: &mut impl Read) -> Result<Tag, Error> { // 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<R>(stream: &mut R) -> Result<Tag, Error> - where - R: AsyncBufRead + std::marker::Unpin + std::marker::Send, - { + pub fn read_zlib(stream: &mut impl BufRead) -> Result<Tag, Error> { let mut gz = ZlibDecoder::new(stream); - Tag::read(&mut gz).await + Tag::read(&mut gz) } - pub async fn read_gzip<R>(stream: &mut R) -> Result<Tag, Error> - where - R: AsyncBufRead + std::marker::Unpin + std::marker::Send, - { - let mut gz = GzipDecoder::new(stream); - Tag::read(&mut gz).await + pub fn read_gzip(stream: &mut impl Read) -> Result<Tag, Error> { + 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); } |
