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! {
|
||||
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() {
|
||||
#(#matchers)*
|
||||
_ => None,
|
||||
|
|
|
@ -60,67 +60,7 @@ impl<'a: 'tape, 'tape> NbtCompound<'a, 'tape> {
|
|||
unchecked_write_string(data, name);
|
||||
}
|
||||
|
||||
let (kind, _) = 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 = 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:?}"),
|
||||
}
|
||||
write_tag(tag, data);
|
||||
}
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
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]> {
|
||||
let (kind, value) = self.element();
|
||||
if kind != TapeTagKind::ByteList {
|
||||
|
@ -827,6 +833,16 @@ where
|
|||
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
|
||||
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 };
|
||||
|
|
|
@ -253,23 +253,38 @@ impl<'a> Debug for BaseNbt<'a> {
|
|||
pub struct BaseNbtCompound<'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.
|
||||
pub struct BaseNbtTag<'a> {
|
||||
tapes: Tapes<'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
|
||||
'a: 'tape,
|
||||
{
|
||||
NbtCompound {
|
||||
NbtTag {
|
||||
element: self.tapes.main.as_ptr(),
|
||||
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.
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub enum Nbt<'a> {
|
||||
|
@ -677,7 +692,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn read_complexplayer_with_given_alloc() {
|
||||
fn read_complex_player_as_tag() {
|
||||
let src = include_bytes!("../../tests/complex_player.dat").to_vec();
|
||||
let mut src_slice = src.as_slice();
|
||||
let mut decoded_src_decoder = GzDecoder::new(&mut src_slice);
|
||||
|
@ -690,7 +705,7 @@ mod tests {
|
|||
decoded_src_as_tag.push(END_ID);
|
||||
|
||||
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.list("Rotation").unwrap().floats().unwrap().len(), 2);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue