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:
parent
31be4d3231
commit
0549a7c569
4 changed files with 96 additions and 67 deletions
|
@ -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,
|
||||||
|
|
|
@ -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:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue