mirror of
https://github.com/azalea-rs/simdnbt.git
synced 2025-08-02 07:26:04 +00:00
use a mutable slice and read without byteorder
This commit is contained in:
parent
ecb0c42f1f
commit
bdeed25d85
12 changed files with 216 additions and 71 deletions
|
@ -18,10 +18,10 @@ The difference is that the "borrow" variant requires you to keep a reference to
|
|||
```rust,no_run
|
||||
use std::borrow::Cow;
|
||||
use std::io::Cursor;
|
||||
use simdnbt::borrow::Nbt;
|
||||
use simdnbt::borrow::{cursor::McCursor, Nbt};
|
||||
|
||||
fn example(item_bytes: &[u8]) {
|
||||
let nbt = Nbt::read(&mut Cursor::new(item_bytes))
|
||||
let nbt = Nbt::read(&mut McCursor::new(item_bytes))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let skyblock_id: Cow<str> = nbt
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::{
|
|||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
|
||||
use flate2::read::GzDecoder;
|
||||
use simdnbt::borrow::cursor::McCursor;
|
||||
|
||||
pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
||||
let mut file = File::open(format!("tests/{filename}")).unwrap();
|
||||
|
@ -35,7 +36,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
|||
// })
|
||||
// });
|
||||
|
||||
let nbt = simdnbt::borrow::Nbt::read(&mut Cursor::new(input))
|
||||
let nbt = simdnbt::borrow::Nbt::read(&mut McCursor::new(input))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
group.bench_function("simdnbt_borrow_write", |b| {
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
|||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
|
||||
use flate2::read::GzDecoder;
|
||||
use simdnbt::borrow::cursor::McCursor;
|
||||
|
||||
pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
||||
let mut file = File::open(format!("tests/{filename}")).unwrap();
|
||||
|
@ -33,7 +34,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
|||
graphite_items_from_nbt(graphite_binary::nbt::decode::read(&mut &input[..]).unwrap())
|
||||
.unwrap();
|
||||
let simdnbt_nbt = simdnbt_items_from_nbt(
|
||||
simdnbt::borrow::Nbt::read(&mut Cursor::new(input))
|
||||
simdnbt::borrow::Nbt::read(&mut McCursor::new(input))
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
)
|
||||
|
@ -63,7 +64,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
|||
group.bench_function("simdnbt_parse", |b| {
|
||||
b.iter(|| {
|
||||
let input = black_box(input);
|
||||
let nbt = black_box(simdnbt::borrow::Nbt::read(&mut Cursor::new(input)));
|
||||
let nbt = black_box(simdnbt::borrow::Nbt::read(&mut McCursor::new(input)));
|
||||
let nbt = nbt.unwrap().unwrap();
|
||||
black_box(simdnbt_items_from_nbt(nbt));
|
||||
})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
|
||||
use flate2::read::GzDecoder;
|
||||
use simdnbt::borrow::cursor::McCursor;
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{Cursor, Read},
|
||||
|
@ -19,19 +20,18 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
|||
decoded_src = contents;
|
||||
}
|
||||
|
||||
let mut decoded_src_stream = Cursor::new(&decoded_src[..]);
|
||||
|
||||
let mut group = c.benchmark_group(format!("nbt/{filename}"));
|
||||
|
||||
group.throughput(Throughput::Bytes(decoded_src.len() as u64));
|
||||
|
||||
group.bench_function("Decode", |b| {
|
||||
b.iter(|| {
|
||||
let mut decoded_src_stream = McCursor::new(&decoded_src[..]);
|
||||
black_box(simdnbt::borrow::Nbt::read(&mut decoded_src_stream).unwrap());
|
||||
decoded_src_stream.set_position(0);
|
||||
})
|
||||
});
|
||||
|
||||
let mut decoded_src_stream = McCursor::new(&decoded_src[..]);
|
||||
let nbt = simdnbt::borrow::Nbt::read(&mut decoded_src_stream)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::HashMap, hint::black_box, io::Cursor};
|
||||
|
||||
use simdnbt::{Deserialize, Serialize};
|
||||
use simdnbt::{borrow::cursor::McCursor, Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
pub struct Item {
|
||||
|
@ -68,7 +68,7 @@ fn main() {
|
|||
let input = black_box(include_bytes!("../tests/realworld.nbt"));
|
||||
|
||||
for _ in 0..1 {
|
||||
let nbt = simdnbt::borrow::Nbt::read(&mut Cursor::new(input));
|
||||
let nbt = simdnbt::borrow::Nbt::read(&mut McCursor::new(input));
|
||||
let nbt = black_box(nbt.unwrap().unwrap());
|
||||
|
||||
let data = Base::from_nbt(&nbt).unwrap();
|
||||
|
@ -76,7 +76,7 @@ fn main() {
|
|||
// roundtrip
|
||||
let mut new_nbt_bytes = Vec::new();
|
||||
data.clone().to_nbt().write(&mut new_nbt_bytes);
|
||||
let new_nbt = simdnbt::borrow::Nbt::read(&mut Cursor::new(&new_nbt_bytes[..]))
|
||||
let new_nbt = simdnbt::borrow::Nbt::read(&mut McCursor::new(&new_nbt_bytes[..]))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let new_data = Base::from_nbt(&new_nbt).unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::HashMap, hint::black_box, io::Cursor};
|
||||
|
||||
use simdnbt::borrow::{BaseNbt, Nbt};
|
||||
use simdnbt::borrow::{cursor::McCursor, BaseNbt, Nbt};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub struct Item {
|
||||
|
@ -103,7 +103,7 @@ fn main() {
|
|||
let input = black_box(include_bytes!("../tests/realworld.nbt"));
|
||||
|
||||
for _ in 0..1 {
|
||||
let nbt = Nbt::read(&mut Cursor::new(input));
|
||||
let nbt = Nbt::read(&mut McCursor::new(input));
|
||||
let nbt = black_box(nbt.unwrap().unwrap());
|
||||
black_box(items_from_nbt(nbt));
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
use super::{list::NbtList, NbtTag};
|
||||
use super::{cursor::McCursor, list::NbtList, NbtTag};
|
||||
|
||||
/// A list of named tags. The order of the tags is preserved.
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
|
@ -23,11 +23,11 @@ impl<'a> NbtCompound<'a> {
|
|||
Self { values }
|
||||
}
|
||||
|
||||
pub fn read(data: &mut Cursor<&'a [u8]>) -> Result<Self, Error> {
|
||||
pub fn read(data: &mut McCursor<'a>) -> Result<Self, Error> {
|
||||
Self::read_with_depth(data, 0)
|
||||
}
|
||||
|
||||
pub fn read_with_depth(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
|
||||
pub fn read_with_depth(data: &mut McCursor<'a>, depth: usize) -> Result<Self, Error> {
|
||||
if depth > MAX_DEPTH {
|
||||
return Err(Error::MaxDepthExceeded);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl<'a> NbtCompound<'a> {
|
|||
if tag_type == END_ID {
|
||||
break;
|
||||
}
|
||||
let tag_name = read_string(data)?;
|
||||
let tag_name = data.read_string()?;
|
||||
|
||||
values.push((tag_name, NbtTag::read_with_type(data, tag_type, depth)?));
|
||||
}
|
||||
|
|
138
simdnbt/src/borrow/cursor.rs
Normal file
138
simdnbt/src/borrow/cursor.rs
Normal file
|
@ -0,0 +1,138 @@
|
|||
use crate::{
|
||||
common::{read_u8_array, slice_u8_into_i8},
|
||||
raw_list::RawList,
|
||||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
pub struct McCursor<'a> {
|
||||
slice: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> McCursor<'a> {
|
||||
pub fn new(slice: &'a [u8]) -> Self {
|
||||
Self { slice }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn try_read_exact(&mut self, n: usize) -> Result<&'a [u8], Error> {
|
||||
if n > self.slice.len() {
|
||||
return Err(Error::UnexpectedEof);
|
||||
}
|
||||
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
|
||||
// fulfills the requirements of `split_at_unchecked`.
|
||||
let (a, b) = unsafe { self.slice.split_at_unchecked(n) };
|
||||
self.slice = b;
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) -> Result<(), Error> {
|
||||
if n > self.slice.len() {
|
||||
return Err(Error::UnexpectedEof);
|
||||
}
|
||||
self.slice = &self.slice[n..];
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_i8(&mut self) -> Result<i8, Error> {
|
||||
Ok(<i8>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<i8>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<i8>()])
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u8(&mut self) -> Result<u8, Error> {
|
||||
self.read_i8().map(|x| x as u8)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_i16(&mut self) -> Result<i16, Error> {
|
||||
Ok(<i16>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<i16>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<i16>()])
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_i32(&mut self) -> Result<i32, Error> {
|
||||
Ok(<i32>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<i32>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<i32>()])
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_u32(&mut self) -> Result<u32, Error> {
|
||||
self.read_i32().map(|x| x as u32)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_i64(&mut self) -> Result<i64, Error> {
|
||||
Ok(<i64>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<i64>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<i64>()])
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_f32(&mut self) -> Result<f32, Error> {
|
||||
Ok(<f32>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<f32>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<f32>()])
|
||||
}))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_f64(&mut self) -> Result<f64, Error> {
|
||||
Ok(<f64>::from_be_bytes(unsafe {
|
||||
*(self.try_read_exact(core::mem::size_of::<f64>())?.as_ptr()
|
||||
as *const [u8; core::mem::size_of::<f64>()])
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn read_with_u32_length<'b>(&mut self, width: usize) -> Result<&'a [u8], Error> {
|
||||
let length = self.read_i32()?;
|
||||
let length_in_bytes = length as usize * width;
|
||||
// make sure we don't read more than the length
|
||||
if self.slice.len() < length_in_bytes {
|
||||
return Err(Error::UnexpectedEof);
|
||||
}
|
||||
let (a, b) = self.slice.split_at(length_in_bytes);
|
||||
self.slice = b;
|
||||
Ok(a)
|
||||
}
|
||||
|
||||
pub fn read_with_u16_length<'b>(&mut self, width: usize) -> Result<&'a [u8], Error> {
|
||||
let length = self.read_i16()? as u16;
|
||||
let length_in_bytes = length as usize * width;
|
||||
// make sure we don't read more than the length
|
||||
if self.slice.len() < length_in_bytes {
|
||||
return Err(Error::UnexpectedEof);
|
||||
}
|
||||
self.try_read_exact(length_in_bytes)
|
||||
}
|
||||
|
||||
pub fn read_string(&mut self) -> Result<&'a Mutf8Str, Error> {
|
||||
let data = self.read_with_u16_length(1)?;
|
||||
Ok(Mutf8Str::from_slice(data))
|
||||
}
|
||||
|
||||
pub fn read_int_array(&mut self) -> Result<RawList<'a, i32>, Error> {
|
||||
let array_bytes = self.read_with_u32_length(4)?;
|
||||
Ok(RawList::new(array_bytes))
|
||||
}
|
||||
|
||||
pub fn read_long_array(&mut self) -> Result<RawList<'a, i64>, Error> {
|
||||
let array_bytes = self.read_with_u32_length(8)?;
|
||||
Ok(RawList::new(array_bytes))
|
||||
}
|
||||
|
||||
pub fn read_u8_array(&mut self) -> Result<&'a [u8], Error> {
|
||||
self.read_with_u32_length(1)
|
||||
}
|
||||
pub fn read_i8_array(&mut self) -> Result<&'a [i8], Error> {
|
||||
Ok(slice_u8_into_i8(self.read_u8_array()?))
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
use super::{read_u32, NbtCompound, MAX_DEPTH};
|
||||
use super::{cursor::McCursor, read_u32, NbtCompound, MAX_DEPTH};
|
||||
|
||||
/// A list of NBT tags of a single type.
|
||||
#[repr(u8)]
|
||||
|
@ -35,42 +35,42 @@ pub enum NbtList<'a> {
|
|||
LongArray(Vec<RawList<'a, i64>>) = LONG_ARRAY_ID,
|
||||
}
|
||||
impl<'a> NbtList<'a> {
|
||||
pub fn read(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
|
||||
pub fn read(data: &mut McCursor<'a>, depth: usize) -> Result<Self, Error> {
|
||||
if depth > MAX_DEPTH {
|
||||
return Err(Error::MaxDepthExceeded);
|
||||
}
|
||||
let tag_type = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
|
||||
Ok(match tag_type {
|
||||
END_ID => {
|
||||
data.set_position(data.position() + 4);
|
||||
data.advance(4);
|
||||
NbtList::Empty
|
||||
}
|
||||
BYTE_ID => NbtList::Byte(read_i8_array(data)?),
|
||||
SHORT_ID => NbtList::Short(RawList::new(read_with_u32_length(data, 2)?)),
|
||||
INT_ID => NbtList::Int(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
LONG_ID => NbtList::Long(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => NbtList::Float(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => NbtList::Double(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ID => NbtList::Byte(data.read_i8_array()?),
|
||||
SHORT_ID => NbtList::Short(RawList::new(data.read_with_u32_length(2)?)),
|
||||
INT_ID => NbtList::Int(RawList::new(data.read_with_u32_length(4)?)),
|
||||
LONG_ID => NbtList::Long(RawList::new(data.read_with_u32_length(8)?)),
|
||||
FLOAT_ID => NbtList::Float(RawList::new(data.read_with_u32_length(4)?)),
|
||||
DOUBLE_ID => NbtList::Double(RawList::new(data.read_with_u32_length(8)?)),
|
||||
BYTE_ARRAY_ID => NbtList::ByteArray({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
arrays.push(read_u8_array(data)?)
|
||||
arrays.push(data.read_u8_array()?)
|
||||
}
|
||||
arrays
|
||||
}),
|
||||
STRING_ID => NbtList::String({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut strings = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
strings.push(read_string(data)?)
|
||||
strings.push(data.read_string()?)
|
||||
}
|
||||
strings
|
||||
}),
|
||||
LIST_ID => NbtList::List({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut lists = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
|
@ -79,7 +79,7 @@ impl<'a> NbtList<'a> {
|
|||
lists
|
||||
}),
|
||||
COMPOUND_ID => NbtList::Compound({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut compounds = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
|
@ -88,20 +88,20 @@ impl<'a> NbtList<'a> {
|
|||
compounds
|
||||
}),
|
||||
INT_ARRAY_ID => NbtList::IntArray({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
arrays.push(read_int_array(data)?)
|
||||
arrays.push(data.read_int_array()?)
|
||||
}
|
||||
arrays
|
||||
}),
|
||||
LONG_ARRAY_ID => NbtList::LongArray({
|
||||
let length = read_u32(data)?;
|
||||
let length = data.read_u32()?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
arrays.push(read_long_array(data)?)
|
||||
arrays.push(data.read_long_array()?)
|
||||
}
|
||||
arrays
|
||||
}),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! The borrowed variant of NBT. This is useful if you're only reading data and you can keep a reference to the original buffer.
|
||||
|
||||
mod compound;
|
||||
pub mod cursor;
|
||||
mod list;
|
||||
|
||||
use std::{io::Cursor, ops::Deref};
|
||||
|
@ -17,6 +18,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
use self::cursor::McCursor;
|
||||
pub use self::{compound::NbtCompound, list::NbtList};
|
||||
|
||||
/// A complete NBT container. This contains a name and a compound tag.
|
||||
|
@ -35,7 +37,7 @@ pub enum Nbt<'a> {
|
|||
|
||||
impl<'a> Nbt<'a> {
|
||||
/// Reads NBT from the given data. Returns `Ok(None)` if there is no data.
|
||||
pub fn read(data: &mut Cursor<&'a [u8]>) -> Result<Nbt<'a>, Error> {
|
||||
pub fn read(data: &mut McCursor<'a>) -> Result<Nbt<'a>, Error> {
|
||||
let root_type = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
|
||||
if root_type == END_ID {
|
||||
return Ok(Nbt::None);
|
||||
|
@ -43,7 +45,7 @@ impl<'a> Nbt<'a> {
|
|||
if root_type != COMPOUND_ID {
|
||||
return Err(Error::InvalidRootType(root_type));
|
||||
}
|
||||
let name = read_string(data)?;
|
||||
let name = data.read_string()?;
|
||||
let tag = NbtCompound::read_with_depth(data, 0)?;
|
||||
|
||||
Ok(Nbt::Some(BaseNbt { name, tag }))
|
||||
|
@ -128,49 +130,45 @@ impl<'a> NbtTag<'a> {
|
|||
unsafe { *<*const _>::from(self).cast::<u8>() }
|
||||
}
|
||||
|
||||
fn read_with_type(
|
||||
data: &mut Cursor<&'a [u8]>,
|
||||
tag_type: u8,
|
||||
depth: usize,
|
||||
) -> Result<Self, Error> {
|
||||
fn read_with_type(data: &mut McCursor<'a>, tag_type: u8, depth: usize) -> Result<Self, Error> {
|
||||
match tag_type {
|
||||
BYTE_ID => Ok(NbtTag::Byte(
|
||||
data.read_i8().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
SHORT_ID => Ok(NbtTag::Short(
|
||||
data.read_i16::<BE>().map_err(|_| Error::UnexpectedEof)?,
|
||||
data.read_i16().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
INT_ID => Ok(NbtTag::Int(
|
||||
data.read_i32::<BE>().map_err(|_| Error::UnexpectedEof)?,
|
||||
data.read_i32().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
LONG_ID => Ok(NbtTag::Long(
|
||||
data.read_i64::<BE>().map_err(|_| Error::UnexpectedEof)?,
|
||||
data.read_i64().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
FLOAT_ID => Ok(NbtTag::Float(
|
||||
data.read_f32::<BE>().map_err(|_| Error::UnexpectedEof)?,
|
||||
data.read_f32().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
DOUBLE_ID => Ok(NbtTag::Double(
|
||||
data.read_f64::<BE>().map_err(|_| Error::UnexpectedEof)?,
|
||||
data.read_f64().map_err(|_| Error::UnexpectedEof)?,
|
||||
)),
|
||||
BYTE_ARRAY_ID => Ok(NbtTag::ByteArray(read_with_u32_length(data, 1)?)),
|
||||
STRING_ID => Ok(NbtTag::String(read_string(data)?)),
|
||||
BYTE_ARRAY_ID => Ok(NbtTag::ByteArray(data.read_with_u32_length(1)?)),
|
||||
STRING_ID => Ok(NbtTag::String(data.read_string()?)),
|
||||
LIST_ID => Ok(NbtTag::List(NbtList::read(data, depth + 1)?)),
|
||||
COMPOUND_ID => Ok(NbtTag::Compound(NbtCompound::read_with_depth(
|
||||
data,
|
||||
depth + 1,
|
||||
)?)),
|
||||
INT_ARRAY_ID => Ok(NbtTag::IntArray(read_int_array(data)?)),
|
||||
LONG_ARRAY_ID => Ok(NbtTag::LongArray(read_long_array(data)?)),
|
||||
INT_ARRAY_ID => Ok(NbtTag::IntArray(data.read_int_array()?)),
|
||||
LONG_ARRAY_ID => Ok(NbtTag::LongArray(data.read_long_array()?)),
|
||||
_ => Err(Error::UnknownTagId(tag_type)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(data: &mut Cursor<&'a [u8]>) -> Result<Self, Error> {
|
||||
pub fn read(data: &mut McCursor<'a>) -> Result<Self, Error> {
|
||||
let tag_type = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
|
||||
Self::read_with_type(data, tag_type, 0)
|
||||
}
|
||||
|
||||
pub fn read_optional(data: &mut Cursor<&'a [u8]>) -> Result<Option<Self>, Error> {
|
||||
pub fn read_optional(data: &mut McCursor<'a>) -> Result<Option<Self>, Error> {
|
||||
let tag_type = data.read_u8().map_err(|_| Error::UnexpectedEof)?;
|
||||
if tag_type == END_ID {
|
||||
return Ok(None);
|
||||
|
@ -282,7 +280,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn hello_world() {
|
||||
let nbt = Nbt::read(&mut Cursor::new(include_bytes!(
|
||||
let nbt = Nbt::read(&mut McCursor::new(include_bytes!(
|
||||
"../../tests/hello_world.nbt"
|
||||
)))
|
||||
.unwrap()
|
||||
|
@ -302,7 +300,9 @@ mod tests {
|
|||
let mut decoded_src_decoder = GzDecoder::new(&mut src_slice);
|
||||
let mut decoded_src = Vec::new();
|
||||
decoded_src_decoder.read_to_end(&mut decoded_src).unwrap();
|
||||
let nbt = Nbt::read(&mut Cursor::new(&decoded_src)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&decoded_src))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(nbt.int("PersistentId"), Some(1946940766));
|
||||
assert_eq!(nbt.list("Rotation").unwrap().floats().unwrap().len(), 2);
|
||||
|
@ -315,7 +315,9 @@ mod tests {
|
|||
let mut decoded_src_decoder = GzDecoder::new(&mut src_slice);
|
||||
let mut decoded_src = Vec::new();
|
||||
decoded_src_decoder.read_to_end(&mut decoded_src).unwrap();
|
||||
let nbt = Nbt::read(&mut Cursor::new(&decoded_src)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&decoded_src))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(nbt.float("foodExhaustionLevel").unwrap() as u32, 2);
|
||||
assert_eq!(nbt.list("Rotation").unwrap().floats().unwrap().len(), 2);
|
||||
|
@ -328,11 +330,13 @@ mod tests {
|
|||
let mut decoded_src_decoder = GzDecoder::new(&mut src_slice);
|
||||
let mut decoded_src = Vec::new();
|
||||
decoded_src_decoder.read_to_end(&mut decoded_src).unwrap();
|
||||
let nbt = Nbt::read(&mut Cursor::new(&decoded_src)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&decoded_src))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let mut out = Vec::new();
|
||||
nbt.write(&mut out);
|
||||
let nbt = Nbt::read(&mut Cursor::new(&out)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&out)).unwrap().unwrap();
|
||||
|
||||
assert_eq!(nbt.float("foodExhaustionLevel").unwrap() as u32, 2);
|
||||
assert_eq!(nbt.list("Rotation").unwrap().floats().unwrap().len(), 2);
|
||||
|
@ -340,7 +344,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn inttest_1023() {
|
||||
let nbt = Nbt::read(&mut Cursor::new(include_bytes!(
|
||||
let nbt = Nbt::read(&mut McCursor::new(include_bytes!(
|
||||
"../../tests/inttest1023.nbt"
|
||||
)))
|
||||
.unwrap()
|
||||
|
@ -368,7 +372,7 @@ mod tests {
|
|||
}
|
||||
data.write_u8(END_ID).unwrap();
|
||||
|
||||
let nbt = Nbt::read(&mut Cursor::new(&data)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&data)).unwrap().unwrap();
|
||||
let ints = nbt.list("").unwrap().ints().unwrap();
|
||||
for (i, &item) in ints.iter().enumerate() {
|
||||
assert_eq!(i as i32, item);
|
||||
|
@ -390,7 +394,7 @@ mod tests {
|
|||
}
|
||||
data.write_u8(END_ID).unwrap();
|
||||
|
||||
let nbt = Nbt::read(&mut Cursor::new(&data)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&data)).unwrap().unwrap();
|
||||
let ints = nbt.list("").unwrap().ints().unwrap();
|
||||
for (i, &item) in ints.iter().enumerate() {
|
||||
assert_eq!(i as i32, item);
|
||||
|
@ -412,7 +416,7 @@ mod tests {
|
|||
}
|
||||
data.write_u8(END_ID).unwrap();
|
||||
|
||||
let nbt = Nbt::read(&mut Cursor::new(&data)).unwrap().unwrap();
|
||||
let nbt = Nbt::read(&mut McCursor::new(&data)).unwrap().unwrap();
|
||||
let ints = nbt.list("").unwrap().longs().unwrap();
|
||||
for (i, &item) in ints.iter().enumerate() {
|
||||
assert_eq!(i as i64, item);
|
||||
|
@ -426,13 +430,13 @@ mod tests {
|
|||
|
||||
// let mut out = Vec::new();
|
||||
// out.write_u8(COMPOUND_ID).unwrap();
|
||||
// out.write_u16::<BE>(0).unwrap();
|
||||
// out.write_u16(0).unwrap();
|
||||
// out.write_u8(LIST_ID).unwrap();
|
||||
// out.write_u16::<BE>(0).unwrap();
|
||||
// out.write_u16(0).unwrap();
|
||||
// out.write_u8(INT_ID).unwrap();
|
||||
// out.write_i32::<BE>(1023).unwrap();
|
||||
// out.write_i32(1023).unwrap();
|
||||
// for i in 0..1023 {
|
||||
// out.write_i32::<BE>(i).unwrap();
|
||||
// out.write_i32(i).unwrap();
|
||||
// }
|
||||
// out.write_u8(END_ID).unwrap();
|
||||
|
||||
|
@ -443,11 +447,11 @@ mod tests {
|
|||
// fn generate_stringtest() {
|
||||
// let mut out = Vec::new();
|
||||
// out.write_u8(COMPOUND_ID).unwrap();
|
||||
// out.write_u16::<BE>(0).unwrap();
|
||||
// out.write_u16(0).unwrap();
|
||||
// out.write_u8(LIST_ID).unwrap();
|
||||
// out.write_u16::<BE>(0).unwrap();
|
||||
// out.write_u16(0).unwrap();
|
||||
// out.write_u8(STRING_ID).unwrap();
|
||||
// out.write_i32::<BE>(16).unwrap();
|
||||
// out.write_i32(16).unwrap();
|
||||
// out.extend_from_slice(&std::fs::read("tests/stringtest.nbt").unwrap().as_slice()[13..]);
|
||||
// out.write_u8(END_ID).unwrap();
|
||||
// std::fs::write("tests/stringtest2.nbt", out).unwrap();
|
||||
|
|
|
@ -104,7 +104,7 @@ pub fn read_long_array<'a>(data: &mut Cursor<&'a [u8]>) -> Result<RawList<'a, i6
|
|||
Ok(RawList::new(array_bytes))
|
||||
}
|
||||
|
||||
fn slice_u8_into_i8(s: &[u8]) -> &[i8] {
|
||||
pub(crate) fn slice_u8_into_i8(s: &[u8]) -> &[i8] {
|
||||
unsafe { slice::from_raw_parts(s.as_ptr() as *const i8, s.len()) }
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#![feature(portable_simd)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(split_array)]
|
||||
#![feature(slice_split_at_unchecked)]
|
||||
|
||||
pub mod borrow;
|
||||
mod common;
|
||||
|
|
Loading…
Add table
Reference in a new issue