mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-20 07:02:31 +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",
|
"flate2",
|
||||||
"graphite_binary",
|
"graphite_binary",
|
||||||
"log",
|
"log",
|
||||||
|
"packed_simd_2",
|
||||||
"serde",
|
"serde",
|
||||||
"valence_nbt",
|
"valence_nbt",
|
||||||
]
|
]
|
||||||
|
@ -1514,6 +1515,12 @@ version = "0.2.140"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
|
@ -1740,6 +1747,16 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
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]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
|
|
@ -15,6 +15,7 @@ compact_str = { version = "0.7.0", features = ["serde"] }
|
||||||
enum-as-inner = "0.5.1"
|
enum-as-inner = "0.5.1"
|
||||||
flate2 = "^1.0.25"
|
flate2 = "^1.0.25"
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
packed_simd_2 = "0.3.8"
|
||||||
serde = { version = "1.0.152", features = ["derive"], optional = true }
|
serde = { version = "1.0.152", features = ["derive"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench(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/simple_player.dat", c);
|
||||||
// bench_read_file("tests/complex_player.dat", c);
|
// bench_read_file("tests/complex_player.dat", c);
|
||||||
// bench_read_file("tests/level.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
|
// 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_decoder = GzDecoder::new(&mut src);
|
||||||
let mut decoded_src = Vec::new();
|
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[..]);
|
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.throughput(Throughput::Bytes(decoded_src.len() as u64));
|
||||||
|
|
||||||
group.bench_function("Decode", |b| {
|
// group.bench_function("Decode", |b| {
|
||||||
b.iter(|| {
|
// b.iter(|| {
|
||||||
black_box(Nbt::read(&mut decoded_src_stream).unwrap());
|
// black_box(Nbt::read(&mut decoded_src_stream).unwrap());
|
||||||
decoded_src_stream.set_position(0);
|
// decoded_src_stream.set_position(0);
|
||||||
})
|
// })
|
||||||
});
|
// });
|
||||||
|
|
||||||
// group.bench_function("Encode", |b| {
|
// group.bench_function("Encode", |b| {
|
||||||
// b.iter(|| {
|
// b.iter(|| {
|
||||||
|
@ -41,7 +44,16 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
||||||
|
|
||||||
group.bench_function("Get", |b| {
|
group.bench_function("Get", |b| {
|
||||||
b.iter(|| {
|
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();
|
group.finish();
|
||||||
|
@ -53,7 +65,10 @@ fn bench(c: &mut Criterion) {
|
||||||
// bench_file("tests/complex_player.dat", c);
|
// bench_file("tests/complex_player.dat", c);
|
||||||
// bench_file("tests/level.dat", c);
|
// bench_file("tests/level.dat", c);
|
||||||
// bench_file("tests/stringtest.nbt", 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);
|
criterion_group!(benches, bench);
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::tag::*;
|
||||||
use azalea_buf::McBufWritable;
|
use azalea_buf::McBufWritable;
|
||||||
use byteorder::{WriteBytesExt, BE};
|
use byteorder::{WriteBytesExt, BE};
|
||||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||||
|
use packed_simd_2::{i32x16, i32x2, i32x4, i32x8, i64x2, i64x4, i64x8};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -81,14 +82,78 @@ fn write_list(writer: &mut impl Write, value: &NbtList) {
|
||||||
}
|
}
|
||||||
NbtList::Int(l) => {
|
NbtList::Int(l) => {
|
||||||
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
||||||
for &v in l {
|
// flip the bits to big endian with simd
|
||||||
writer.write_i32::<BE>(v).unwrap();
|
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) => {
|
NbtList::Long(l) => {
|
||||||
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
writer.write_i32::<BE>(l.len() as i32).unwrap();
|
||||||
for &v in l {
|
// flip the bits to big endian with simd
|
||||||
writer.write_i64::<BE>(v).unwrap();
|
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) => {
|
NbtList::Float(l) => {
|
||||||
|
|
|
@ -48,6 +48,17 @@ pub enum Nbt {
|
||||||
IntArray(NbtIntArray) = INT_ARRAY_ID,
|
IntArray(NbtIntArray) = INT_ARRAY_ID,
|
||||||
LongArray(NbtLongArray) = LONG_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.
|
/// An NBT value.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
@ -69,17 +80,6 @@ pub enum NbtList {
|
||||||
LongArray(Vec<NbtLongArray>) = LONG_ARRAY_ID,
|
LongArray(Vec<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>() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl NbtList {
|
impl NbtList {
|
||||||
/// Get the numerical ID of the tag type.
|
/// Get the numerical ID of the tag type.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -91,6 +91,66 @@ impl NbtList {
|
||||||
unsafe { *<*const _>::from(self).cast::<u8>() }
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// thanks to Moulberry/Graphite for the idea to use a vec and binary search
|
// thanks to Moulberry/Graphite for the idea to use a vec and binary search
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
#[derive(Debug, Clone, Default, PartialEq)]
|
||||||
|
@ -161,7 +221,9 @@ impl NbtCompound {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_worth_sorting(&self) -> bool {
|
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")]
|
#[cfg(feature = "serde")]
|
||||||
|
@ -191,3 +253,9 @@ impl FromIterator<(NbtString, Nbt)> for NbtCompound {
|
||||||
Self { inner }
|
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;
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -108,3 +108,33 @@ fn test_simple_player() {
|
||||||
|
|
||||||
assert_eq!(decoded_tag, original_tag);
|
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