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

represent longs and doubles as a pointer in the tape instead of two elements

This commit is contained in:
mat 2025-01-17 08:55:09 +00:00
parent 4f1b4460f2
commit 75fa78057c
3 changed files with 31 additions and 16 deletions

View file

@ -348,20 +348,18 @@ pub(crate) fn read_tag<'a>(
TapeElement::new_with_u32(TapeTagKind::Int, int as u32)
}
LONG_ID => {
let long = data.read_i64()?;
tapes.main.push(TapeElement::new_with_0(TapeTagKind::Long));
TapeElement::new(long as u64)
let long_ptr = data.cur;
data.skip(8)?;
TapeElement::new_with_ptr(TapeTagKind::Long, long_ptr)
}
FLOAT_ID => {
let float = data.read_f32()?;
TapeElement::new_with_u32(TapeTagKind::Float, float.to_bits())
}
DOUBLE_ID => {
let double = data.read_f64()?;
tapes
.main
.push(TapeElement::new_with_0(TapeTagKind::Double));
TapeElement::new(double.to_bits())
let double_ptr = data.cur;
data.skip(8)?;
TapeElement::new_with_ptr(TapeTagKind::Double, double_ptr)
}
BYTE_ARRAY_ID => {
let byte_array_ptr = data.cur;
@ -390,6 +388,7 @@ pub(crate) fn read_tag<'a>(
}
_ => return Err(NonRootError::unknown_tag_id(tag_type)),
};
tapes.main.push(pushing_element);
Ok(())
}

View file

@ -11,7 +11,7 @@ use std::{
};
use byteorder::ReadBytesExt;
use tape::{UnalignedU16, UnalignedU32};
use tape::{UnalignedU16, UnalignedU32, UnalignedU64};
use crate::{
common::{
@ -382,9 +382,10 @@ impl<'a: 'tape, 'tape> NbtTag<'a, 'tape> {
pub fn long(&self) -> Option<i64> {
let el = self.element();
ensure_kind(el, TapeTagKind::Long)?;
// the value is in the next element because longs are too big to fit in a single element
let value_el = unsafe { *self.element.add(1) };
Some(value_el.u64() as i64)
// longs are 64 bits so since we can't fit the kind and value in a
// single element, we store a pointer to them instead
let long_ptr = el.ptr::<UnalignedU64>();
Some(u64::from(unsafe { *long_ptr }).to_be() as i64)
}
pub fn float(&self) -> Option<f32> {
let el = self.element();
@ -394,9 +395,9 @@ impl<'a: 'tape, 'tape> NbtTag<'a, 'tape> {
pub fn double(&self) -> Option<f64> {
let el = self.element();
ensure_kind(el, TapeTagKind::Double)?;
// the value is in the next element because doubles are too big to fit in a single element
let value_el = unsafe { *self.element.add(1) };
Some(f64::from_bits(value_el.u64()))
// see the comment above for longs, doubles are also 64 bits so the same applies
let double_ptr = el.ptr::<UnalignedU64>();
Some(f64::from_bits(u64::from(unsafe { *double_ptr }).to_be()))
}
pub fn byte_array(&self) -> Option<&'a [u8]> {
let el = self.element();

View file

@ -109,7 +109,6 @@ impl TapeElement {
/// The element must be a tag and not something else like a continuation of a long or double.
pub unsafe fn skip_offset(&self) -> usize {
match self.kind() {
TapeTagKind::Long | TapeTagKind::Double => 2,
TapeTagKind::Compound | TapeTagKind::ListList | TapeTagKind::CompoundList => {
self.approx_len_and_offset().1 as usize
}
@ -176,6 +175,22 @@ impl From<u24> for u32 {
}
}
#[derive(Debug, Copy, Clone)]
#[repr(packed)]
pub struct UnalignedU64(pub u64);
impl From<u64> for UnalignedU64 {
#[inline]
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<UnalignedU64> for u64 {
#[inline]
fn from(value: UnalignedU64) -> Self {
value.0
}
}
#[derive(Debug, Copy, Clone)]
#[repr(packed)]
pub struct UnalignedU32(pub u32);