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:
parent
4f1b4460f2
commit
75fa78057c
3 changed files with 31 additions and 16 deletions
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue