1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 07:26:04 +00:00

optimized reading tag name in read_tag_in_compound

This commit is contained in:
mat 2025-01-19 08:16:18 +00:00
parent c9e8ebe341
commit acb56cd97a
5 changed files with 39 additions and 30 deletions

View file

@ -3,9 +3,9 @@ use std::mem::MaybeUninit;
use crate::{
common::{
extend_unchecked, push_unchecked, read_int_array, read_long_array, read_string,
read_with_u32_length, skip_string, write_string, write_string_unchecked, BYTE_ARRAY_ID,
BYTE_ID, COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID,
LONG_ARRAY_ID, LONG_ID, MAX_DEPTH, SHORT_ID, STRING_ID,
read_with_u32_length, write_string, write_string_unchecked, BYTE_ARRAY_ID, BYTE_ID,
COMPOUND_ID, DOUBLE_ID, END_ID, FLOAT_ID, INT_ARRAY_ID, INT_ID, LIST_ID, LONG_ARRAY_ID,
LONG_ID, MAX_DEPTH, SHORT_ID, STRING_ID,
},
error::NonRootError,
reader::Reader,
@ -237,7 +237,7 @@ pub(crate) struct ParsingStackElement {
pub kind: ParsingStackElementKind,
pub index: u32,
}
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub(crate) enum ParsingStackElementKind {
Compound,
@ -413,7 +413,7 @@ pub(crate) fn read_tag<'a>(
Ok(())
}
#[inline(always)]
#[inline]
pub(crate) fn read_tag_in_compound<'a>(
data: &mut Reader<'a>,
tapes: &mut Tapes<'a>,
@ -427,7 +427,27 @@ pub(crate) fn read_tag_in_compound<'a>(
let tag_name_ptr = data.cur;
debug_assert_eq!(tag_name_ptr as u64 >> 56, 0);
skip_string(data)?;
// read the string in a more efficient way than just calling read_string
let mut cur_addr = tag_name_ptr as usize;
let end_addr = data.end_addr();
cur_addr += 2;
if cur_addr > end_addr {
return Err(NonRootError::unexpected_eof());
}
// this actually results in an extra instruction since it sets the data.cur
// unnecessarily, but for some reason it's faster anyways
let length = unsafe { data.read_type_unchecked::<u16>() }.to_be();
let length_in_bytes: usize = length as usize;
cur_addr += length_in_bytes;
if cur_addr > end_addr {
return Err(NonRootError::unexpected_eof());
}
data.cur = cur_addr as *const u8;
// finished reading the string
tapes.main.push(TapeElement::new(tag_name_ptr as u64));
read_tag(data, tapes, stack, tag_type)

View file

@ -34,6 +34,7 @@ impl<'a, 'tape> NbtList<'a, 'tape> {
stack: &mut ParsingStack,
) -> Result<(), NonRootError> {
let tag_type = data.read_u8()?;
let pushing_element = match tag_type {
END_ID => {
// the length is unused for this type of lists

View file

@ -49,25 +49,6 @@ pub fn read_string<'a>(data: &mut Reader<'a>) -> Result<&'a Mutf8Str, Unexpected
Ok(Mutf8Str::from_slice(data))
}
pub fn skip_string(data: &mut Reader<'_>) -> Result<(), UnexpectedEofError> {
let cur_addr = data.cur_addr();
let end_addr = data.end_addr();
if cur_addr + 2 > end_addr {
return Err(UnexpectedEofError);
}
let length = unsafe { data.read_type_unchecked::<u16>() }.to_be();
let length_in_bytes: usize = length as usize;
if cur_addr + 2 + length_in_bytes > end_addr {
return Err(UnexpectedEofError);
}
unsafe { data.skip_unchecked(length_in_bytes) };
Ok(())
}
pub fn read_u8_array<'a>(data: &mut Reader<'a>) -> Result<&'a [u8], UnexpectedEofError> {
read_with_u32_length(data, 1)
}

View file

@ -181,7 +181,7 @@ impl Mutf8String {
Mutf8Str::from_slice(self.vec.as_slice())
}
/// Try to convert this MUTF-8 string into a UTF-8 string. If the data isn't
/// Convert this MUTF-8 string into a UTF-8 string. If the data isn't
/// valid MUTF-8, it'll return an empty string without erroring.
#[inline]
pub fn into_string(self) -> String {
@ -193,6 +193,17 @@ impl Mutf8String {
}
}
/// Try to convert this MUTF-8 string into a UTF-8 string.
#[inline]
pub fn try_into_string(self) -> Result<String, simd_cesu8::DecodingError> {
if is_plain_ascii(&self.vec) {
// SAFETY: &[u8] and &str are the same layout.
Ok(unsafe { String::from_utf8_unchecked(self.vec) })
} else {
mutf8::decode(&self.vec).map(|cow| cow.into_owned())
}
}
#[inline]
pub fn from_string(s: String) -> Mutf8String {
Self::from_vec(mutf8::encode(&s).into_owned())

View file

@ -24,10 +24,6 @@ impl<'a> Reader<'a> {
}
}
#[inline]
pub fn cur_addr(&self) -> usize {
self.cur as usize
}
#[inline]
pub fn end_addr(&self) -> usize {
self.end as usize