1
0
Fork 0
mirror of https://github.com/azalea-rs/simdnbt.git synced 2025-08-02 23:44:40 +00:00

fix macros and make it more useable

This commit is contained in:
mat 2024-07-05 04:22:41 +00:00
commit 0549a7c569
4 changed files with 96 additions and 67 deletions

View file

@ -168,7 +168,7 @@ pub fn from_nbt_tag_derive(input: proc_macro::TokenStream) -> proc_macro::TokenS
let output = quote! { let output = quote! {
impl #generics simdnbt::FromNbtTag for #ident #generics #where_clause { impl #generics simdnbt::FromNbtTag for #ident #generics #where_clause {
fn from_nbt_tag(tag: &simdnbt::borrow::NbtTag) -> Option<Self> { fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
match tag.string()?.to_str().as_ref() { match tag.string()?.to_str().as_ref() {
#(#matchers)* #(#matchers)*
_ => None, _ => None,

View file

@ -60,67 +60,7 @@ impl<'a: 'tape, 'tape> NbtCompound<'a, 'tape> {
unchecked_write_string(data, name); unchecked_write_string(data, name);
} }
let (kind, _) = tag.element(); write_tag(tag, data);
match kind {
TapeTagKind::Byte => unsafe {
unchecked_push(data, tag.byte().unwrap() as u8);
},
TapeTagKind::Short => unsafe {
unchecked_extend(data, &tag.short().unwrap().to_be_bytes());
},
TapeTagKind::Int => unsafe {
unchecked_extend(data, &tag.int().unwrap().to_be_bytes());
},
TapeTagKind::Long => {
data.extend_from_slice(&tag.long().unwrap().to_be_bytes());
}
TapeTagKind::Float => unsafe {
unchecked_extend(data, &tag.float().unwrap().to_be_bytes());
},
TapeTagKind::Double => {
data.extend_from_slice(&tag.double().unwrap().to_be_bytes());
}
TapeTagKind::ByteArray => {
let byte_array = tag.byte_array().unwrap();
unsafe {
unchecked_extend(data, &byte_array.len().to_be_bytes());
}
data.extend_from_slice(byte_array);
}
TapeTagKind::String => {
let string = tag.string().unwrap();
write_string(data, string);
}
_ if kind.is_list() => {
tag.list().unwrap().write(data);
}
TapeTagKind::Compound => {
tag.compound().unwrap().write(data);
}
TapeTagKind::IntArray => {
let int_array = list::u32_prefixed_list_to_rawlist::<i32>(
TapeTagKind::IntArray,
self.element,
)
.unwrap();
unsafe {
unchecked_extend(data, &int_array.len().to_be_bytes());
}
data.extend_from_slice(int_array.as_big_endian());
}
TapeTagKind::LongArray => {
let long_array = list::u32_prefixed_list_to_rawlist::<i64>(
TapeTagKind::LongArray,
self.element,
)
.unwrap();
unsafe {
unchecked_extend(data, &long_array.len().to_be_bytes());
}
data.extend_from_slice(long_array.as_big_endian());
}
_ => unreachable!("Invalid tag kind {kind:?}"),
}
} }
data.push(END_ID); data.push(END_ID);
} }
@ -533,3 +473,61 @@ fn handle_compound_end(tapes: &mut Tapes, stack: &mut ParsingStack) {
.1 = (index_after_end_element as u32 - index_of_compound_element).into(); .1 = (index_after_end_element as u32 - index_of_compound_element).into();
}; };
} }
pub(crate) fn write_tag(tag: NbtTag, data: &mut Vec<u8>) {
let (kind, value) = tag.element();
match kind {
TapeTagKind::Byte => unsafe {
unchecked_push(data, tag.byte().unwrap() as u8);
},
TapeTagKind::Short => unsafe {
unchecked_extend(data, &tag.short().unwrap().to_be_bytes());
},
TapeTagKind::Int => unsafe {
unchecked_extend(data, &tag.int().unwrap().to_be_bytes());
},
TapeTagKind::Long => {
data.extend_from_slice(&tag.long().unwrap().to_be_bytes());
}
TapeTagKind::Float => unsafe {
unchecked_extend(data, &tag.float().unwrap().to_be_bytes());
},
TapeTagKind::Double => {
data.extend_from_slice(&tag.double().unwrap().to_be_bytes());
}
TapeTagKind::ByteArray => {
let byte_array = tag.byte_array().unwrap();
unsafe {
unchecked_extend(data, &byte_array.len().to_be_bytes());
}
data.extend_from_slice(byte_array);
}
TapeTagKind::String => {
let string = tag.string().unwrap();
write_string(data, string);
}
_ if kind.is_list() => {
tag.list().unwrap().write(data);
}
TapeTagKind::Compound => {
tag.compound().unwrap().write(data);
}
TapeTagKind::IntArray => {
let int_array =
unsafe { list::u32_prefixed_list_to_rawlist_unchecked::<i32>(value).unwrap() };
unsafe {
unchecked_extend(data, &int_array.len().to_be_bytes());
}
data.extend_from_slice(int_array.as_big_endian());
}
TapeTagKind::LongArray => {
let long_array =
unsafe { list::u32_prefixed_list_to_rawlist_unchecked::<i64>(value).unwrap() };
unsafe {
unchecked_extend(data, &long_array.len().to_be_bytes());
}
data.extend_from_slice(long_array.as_big_endian());
}
_ => unreachable!("Invalid tag kind {kind:?}"),
}
}

View file

@ -350,6 +350,12 @@ impl<'a, 'tape> NbtList<'a, 'tape> {
} }
} }
/// Returns whether the list is specifically a list with the `empty` tag type. This will return
/// false if the list is any other type (even it has a length of zero).
pub fn empty(&self) -> bool {
self.element().0 == TapeTagKind::EmptyList
}
pub fn bytes(&self) -> Option<&[i8]> { pub fn bytes(&self) -> Option<&[i8]> {
let (kind, value) = self.element(); let (kind, value) = self.element();
if kind != TapeTagKind::ByteList { if kind != TapeTagKind::ByteList {
@ -827,6 +833,16 @@ where
return None; return None;
} }
unsafe { u32_prefixed_list_to_rawlist_unchecked(value) }
}
#[inline]
pub(crate) unsafe fn u32_prefixed_list_to_rawlist_unchecked<'a, T>(
value: TapeTagValue,
) -> Option<RawList<'a, T>>
where
T: Copy + SwappableNumber,
{
// length is always a u32 // length is always a u32
let length_ptr = u64::from(unsafe { value.int_list }) as usize as *const UnalignedU32; let length_ptr = u64::from(unsafe { value.int_list }) as usize as *const UnalignedU32;
let length = unsafe { u32::from(*length_ptr).swap_bytes() as usize }; let length = unsafe { u32::from(*length_ptr).swap_bytes() as usize };

View file

@ -253,23 +253,38 @@ impl<'a> Debug for BaseNbt<'a> {
pub struct BaseNbtCompound<'a> { pub struct BaseNbtCompound<'a> {
tapes: Tapes<'a>, tapes: Tapes<'a>,
} }
impl<'a, 'tape> From<&'a BaseNbtCompound<'a>> for NbtCompound<'a, 'tape> {
fn from(compound: &'a BaseNbtCompound<'a>) -> Self
where
'a: 'tape,
{
NbtCompound {
element: compound.tapes.main.as_ptr(),
extra_tapes: &compound.tapes.extra,
}
}
}
/// A nameless NBT tag. /// A nameless NBT tag.
pub struct BaseNbtTag<'a> { pub struct BaseNbtTag<'a> {
tapes: Tapes<'a>, tapes: Tapes<'a>,
} }
impl<'a> BaseNbtTag<'a> { impl<'a> BaseNbtTag<'a> {
pub fn compound<'tape>(&'a self) -> NbtCompound<'a, 'tape> pub fn as_tag<'tape>(&'a self) -> NbtTag<'a, 'tape>
where where
'a: 'tape, 'a: 'tape,
{ {
NbtCompound { NbtTag {
element: self.tapes.main.as_ptr(), element: self.tapes.main.as_ptr(),
extra_tapes: &self.tapes.extra, extra_tapes: &self.tapes.extra,
} }
} }
} }
impl<'a, 'tape> From<&'a BaseNbtTag<'a>> for NbtTag<'a, 'tape> {
fn from(tag: &'a BaseNbtTag<'a>) -> Self {
tag.as_tag()
}
}
/// Either a complete NBT container, or nothing. /// Either a complete NBT container, or nothing.
#[derive(Debug, PartialEq, Default)] #[derive(Debug, PartialEq, Default)]
pub enum Nbt<'a> { pub enum Nbt<'a> {
@ -677,7 +692,7 @@ mod tests {
} }
#[test] #[test]
fn read_complexplayer_with_given_alloc() { fn read_complex_player_as_tag() {
let src = include_bytes!("../../tests/complex_player.dat").to_vec(); let src = include_bytes!("../../tests/complex_player.dat").to_vec();
let mut src_slice = src.as_slice(); let mut src_slice = src.as_slice();
let mut decoded_src_decoder = GzDecoder::new(&mut src_slice); let mut decoded_src_decoder = GzDecoder::new(&mut src_slice);
@ -690,7 +705,7 @@ mod tests {
decoded_src_as_tag.push(END_ID); decoded_src_as_tag.push(END_ID);
let nbt = super::read_tag(&mut Cursor::new(&decoded_src_as_tag)).unwrap(); let nbt = super::read_tag(&mut Cursor::new(&decoded_src_as_tag)).unwrap();
let nbt = nbt.compound().compound("").unwrap(); let nbt = nbt.as_tag().compound().unwrap().compound("").unwrap();
assert_eq!(nbt.float("foodExhaustionLevel").unwrap() as u32, 2); assert_eq!(nbt.float("foodExhaustionLevel").unwrap() as u32, 2);
assert_eq!(nbt.list("Rotation").unwrap().floats().unwrap().len(), 2); assert_eq!(nbt.list("Rotation").unwrap().floats().unwrap().len(), 2);