mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
fix merge conflict
This commit is contained in:
commit
4b387c320c
10 changed files with 222 additions and 26 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -345,6 +345,7 @@ dependencies = [
|
|||
"flate2",
|
||||
"graphite_binary",
|
||||
"log",
|
||||
"packed_simd_2",
|
||||
"serde",
|
||||
"valence_nbt",
|
||||
]
|
||||
|
@ -1514,6 +1515,12 @@ version = "0.2.140"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
|
@ -1740,6 +1747,16 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "packed_simd_2"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.0.0"
|
||||
|
|
|
@ -15,6 +15,7 @@ compact_str = { version = "0.7.0", features = ["serde"] }
|
|||
enum-as-inner = "0.5.1"
|
||||
flate2 = "^1.0.25"
|
||||
log = "0.4.17"
|
||||
packed_simd_2 = "0.3.8"
|
||||
serde = { version = "1.0.152", features = ["derive"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -79,7 +79,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
|||
}
|
||||
|
||||
fn bench(c: &mut Criterion) {
|
||||
bench_read_file("tests/bigtest.nbt", c);
|
||||
// bench_read_file("tests/bigtest.nbt", c);
|
||||
// bench_read_file("tests/simple_player.dat", c);
|
||||
// bench_read_file("tests/complex_player.dat", c);
|
||||
// bench_read_file("tests/level.dat", c);
|
||||
|
|
|
@ -15,7 +15,10 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
|||
// decode the original src so most of the time isn't spent on unzipping
|
||||
let mut decoded_src_decoder = GzDecoder::new(&mut src);
|
||||
let mut decoded_src = Vec::new();
|
||||
decoded_src_decoder.read_to_end(&mut decoded_src).unwrap();
|
||||
if decoded_src_decoder.read_to_end(&mut decoded_src).is_err() {
|
||||
// oh probably wasn't gzipped then
|
||||
decoded_src = contents;
|
||||
}
|
||||
|
||||
let mut decoded_src_stream = Cursor::new(&decoded_src[..]);
|
||||
|
||||
|
@ -26,12 +29,12 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
|||
|
||||
group.throughput(Throughput::Bytes(decoded_src.len() as u64));
|
||||
|
||||
group.bench_function("Decode", |b| {
|
||||
b.iter(|| {
|
||||
black_box(Nbt::read(&mut decoded_src_stream).unwrap());
|
||||
decoded_src_stream.set_position(0);
|
||||
})
|
||||
});
|
||||
// group.bench_function("Decode", |b| {
|
||||
// b.iter(|| {
|
||||
// black_box(Nbt::read(&mut decoded_src_stream).unwrap());
|
||||
// decoded_src_stream.set_position(0);
|
||||
// })
|
||||
// });
|
||||
|
||||
// group.bench_function("Encode", |b| {
|
||||
// b.iter(|| {
|
||||
|
@ -41,7 +44,16 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
|||
|
||||
group.bench_function("Get", |b| {
|
||||
b.iter(|| {
|
||||
black_box(nbt.as_compound().unwrap().get(""));
|
||||
let level = nbt
|
||||
.as_compound()
|
||||
.unwrap()
|
||||
.get("Level")
|
||||
.unwrap()
|
||||
.as_compound()
|
||||
.unwrap();
|
||||
for (k, _) in level.iter() {
|
||||
black_box(level.get(black_box(k)));
|
||||
}
|
||||
})
|
||||
});
|
||||
group.finish();
|
||||
|
@ -53,7 +65,10 @@ fn bench(c: &mut Criterion) {
|
|||
// bench_file("tests/complex_player.dat", c);
|
||||
// bench_file("tests/level.dat", c);
|
||||
// bench_file("tests/stringtest.nbt", c);
|
||||
// bench_file("tests/inttest.nbt", c);
|
||||
// bench_file("tests/inttest16.nbt", c);
|
||||
|
||||
// bench_file("tests/inttest1023.nbt", c);
|
||||
// bench_file("tests/inttest3.nbt", c);
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench);
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::tag::*;
|
|||
use azalea_buf::McBufWritable;
|
||||
use byteorder::{WriteBytesExt, BE};
|
||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||
use packed_simd_2::{i32x16, i32x2, i32x4, i32x8, i64x2, i64x4, i64x8};
|
||||
use std::io::Write;
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -81,14 +82,78 @@ fn write_list(writer: &mut impl Write, value: &NbtList) {
|
|||
}
|
||||
NbtList::Int(l) => {
|
||||
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
||||
for &v in l {
|
||||
writer.write_i32::<BE>(v).unwrap();
|
||||
// flip the bits to big endian with simd
|
||||
let l = l.as_slice();
|
||||
let mut position = 0;
|
||||
// x16
|
||||
while l.len() - position >= 16 {
|
||||
let l = unsafe { i32x16::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i32x16, [u8; 64]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 16;
|
||||
}
|
||||
// x8
|
||||
if l.len() - position >= 8 {
|
||||
let l = unsafe { i32x8::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i32x8, [u8; 32]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 8;
|
||||
}
|
||||
// x4
|
||||
if l.len() - position >= 4 {
|
||||
let l = unsafe { i32x4::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i32x4, [u8; 16]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 4;
|
||||
}
|
||||
// x2
|
||||
if l.len() - position >= 2 {
|
||||
let l = unsafe { i32x2::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i32x2, [u8; 8]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 2;
|
||||
}
|
||||
// x1 ... just a normal write_i32
|
||||
if l.len() - position >= 1 {
|
||||
writer.write_i32::<BE>(l[position]).unwrap();
|
||||
}
|
||||
}
|
||||
NbtList::Long(l) => {
|
||||
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
||||
for &v in l {
|
||||
writer.write_i64::<BE>(v).unwrap();
|
||||
// flip the bits to big endian with simd
|
||||
let l = l.as_slice();
|
||||
let mut position = 0;
|
||||
// x16
|
||||
while l.len() - position >= 8 {
|
||||
let l = unsafe { i64x8::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i64x8, [u8; 64]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 8;
|
||||
}
|
||||
// x4
|
||||
if l.len() - position >= 4 {
|
||||
let l = unsafe { i64x4::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i64x4, [u8; 32]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 4;
|
||||
}
|
||||
// x2
|
||||
if l.len() - position >= 2 {
|
||||
let l = unsafe { i64x2::from_slice_unaligned_unchecked(&l[position..]) };
|
||||
l.to_be();
|
||||
let l = unsafe { std::mem::transmute::<i64x2, [u8; 16]>(l) };
|
||||
writer.write_all(&l).unwrap();
|
||||
position += 2;
|
||||
}
|
||||
// x1 ... just a normal write_i32
|
||||
if l.len() - position >= 1 {
|
||||
writer.write_i64::<BE>(l[position]).unwrap();
|
||||
}
|
||||
}
|
||||
NbtList::Float(l) => {
|
||||
|
|
|
@ -48,6 +48,17 @@ pub enum Nbt {
|
|||
IntArray(NbtIntArray) = INT_ARRAY_ID,
|
||||
LongArray(NbtLongArray) = LONG_ARRAY_ID,
|
||||
}
|
||||
impl Nbt {
|
||||
/// Get the numerical ID of the tag type.
|
||||
#[inline]
|
||||
pub fn id(&self) -> u8 {
|
||||
// SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)`
|
||||
// `union` between `repr(C)` structs, each of which has the `u8`
|
||||
// discriminant as its first field, so we can read the discriminant
|
||||
// without offsetting the pointer.
|
||||
unsafe { *<*const _>::from(self).cast::<u8>() }
|
||||
}
|
||||
}
|
||||
|
||||
/// An NBT value.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -69,7 +80,7 @@ pub enum NbtList {
|
|||
LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID,
|
||||
}
|
||||
|
||||
impl Nbt {
|
||||
impl NbtList {
|
||||
/// Get the numerical ID of the tag type.
|
||||
#[inline]
|
||||
pub fn id(&self) -> u8 {
|
||||
|
@ -80,15 +91,64 @@ impl Nbt {
|
|||
unsafe { *<*const _>::from(self).cast::<u8>() }
|
||||
}
|
||||
}
|
||||
impl NbtList {
|
||||
/// Get the numerical ID of the tag type.
|
||||
#[inline]
|
||||
pub fn id(&self) -> u8 {
|
||||
// SAFETY: Because `Self` is marked `repr(u8)`, its layout is a `repr(C)`
|
||||
// `union` between `repr(C)` structs, each of which has the `u8`
|
||||
// discriminant as its first field, so we can read the discriminant
|
||||
// without offsetting the pointer.
|
||||
unsafe { *<*const _>::from(self).cast::<u8>() }
|
||||
impl From<Vec<NbtByte>> for NbtList {
|
||||
fn from(v: Vec<NbtByte>) -> Self {
|
||||
Self::Byte(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtShort>> for NbtList {
|
||||
fn from(v: Vec<NbtShort>) -> Self {
|
||||
Self::Short(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtInt>> for NbtList {
|
||||
fn from(v: Vec<NbtInt>) -> Self {
|
||||
Self::Int(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtLong>> for NbtList {
|
||||
fn from(v: Vec<NbtLong>) -> Self {
|
||||
Self::Long(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtFloat>> for NbtList {
|
||||
fn from(v: Vec<NbtFloat>) -> Self {
|
||||
Self::Float(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtDouble>> for NbtList {
|
||||
fn from(v: Vec<NbtDouble>) -> Self {
|
||||
Self::Double(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtByteArray>> for NbtList {
|
||||
fn from(v: Vec<NbtByteArray>) -> Self {
|
||||
Self::ByteArray(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtString>> for NbtList {
|
||||
fn from(v: Vec<NbtString>) -> Self {
|
||||
Self::String(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtList>> for NbtList {
|
||||
fn from(v: Vec<NbtList>) -> Self {
|
||||
Self::List(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtCompound>> for NbtList {
|
||||
fn from(v: Vec<NbtCompound>) -> Self {
|
||||
Self::Compound(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtIntArray>> for NbtList {
|
||||
fn from(v: Vec<NbtIntArray>) -> Self {
|
||||
Self::IntArray(v)
|
||||
}
|
||||
}
|
||||
impl From<Vec<NbtLongArray>> for NbtList {
|
||||
fn from(v: Vec<NbtLongArray>) -> Self {
|
||||
Self::LongArray(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +221,9 @@ impl NbtCompound {
|
|||
|
||||
#[inline]
|
||||
fn is_worth_sorting(&self) -> bool {
|
||||
self.inner.len() >= 128
|
||||
// i don't actually know when binary search starts being better, but it's at
|
||||
// least more than 12
|
||||
self.inner.len() >= 32
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -191,3 +253,9 @@ impl FromIterator<(NbtString, Nbt)> for NbtCompound {
|
|||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<(NbtString, Nbt)>> for NbtCompound {
|
||||
fn from(inner: Vec<(NbtString, Nbt)>) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
|
BIN
azalea-nbt/tests/inttest1023.nbt
Normal file
BIN
azalea-nbt/tests/inttest1023.nbt
Normal file
Binary file not shown.
BIN
azalea-nbt/tests/inttest3.nbt
Normal file
BIN
azalea-nbt/tests/inttest3.nbt
Normal file
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
use azalea_nbt::{NbtCompound, NbtList, Nbt};
|
||||
use azalea_nbt::{Nbt, NbtCompound, NbtList};
|
||||
use std::io::Cursor;
|
||||
|
||||
#[test]
|
||||
|
@ -108,3 +108,33 @@ fn test_simple_player() {
|
|||
|
||||
assert_eq!(decoded_tag, original_tag);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_inttest() {
|
||||
// let original = include_bytes!("inttest.nbt").to_vec();
|
||||
|
||||
// let mut original_stream = Cursor::new(original);
|
||||
// let original_tag = Nbt::read_gzip(&mut original_stream).unwrap();
|
||||
|
||||
// let mut result = Vec::new();
|
||||
// original_tag.write(&mut result);
|
||||
|
||||
// let decoded_tag = Nbt::read(&mut Cursor::new(&result)).unwrap();
|
||||
|
||||
// assert_eq!(decoded_tag, original_tag);
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_inttest1023() {
|
||||
let original = include_bytes!("inttest1023.nbt").to_vec();
|
||||
|
||||
let mut original_stream = Cursor::new(original.as_slice());
|
||||
let original_tag = Nbt::read(&mut original_stream).unwrap();
|
||||
|
||||
let mut result = Vec::new();
|
||||
original_tag.write(&mut result);
|
||||
|
||||
let decoded_tag = Nbt::read(&mut Cursor::new(&result)).unwrap();
|
||||
|
||||
assert_eq!(decoded_tag, original_tag);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue