diff --git a/simdnbt-derive/src/lib.rs b/simdnbt-derive/src/lib.rs index 356b9ea..9bc3741 100644 --- a/simdnbt-derive/src/lib.rs +++ b/simdnbt-derive/src/lib.rs @@ -34,7 +34,7 @@ pub fn deserialize_derive(input: proc_macro::TokenStream) -> proc_macro::TokenSt field_deserializers.push(quote! { #struct_field_name: simdnbt::FromNbtTag::from_optional_nbt_tag( - nbt.take(#field_name) + nbt.get(#field_name) )?.ok_or(simdnbt::DeserializeError::MismatchedFieldType(#debug_ident.to_owned()))? }); } @@ -64,7 +64,7 @@ pub fn deserialize_derive(input: proc_macro::TokenStream) -> proc_macro::TokenSt let output = quote! { impl #generics simdnbt::Deserialize for #ident #generics #where_clause { - fn from_compound(mut nbt: simdnbt::owned::NbtCompound) -> Result { + fn from_compound(mut nbt: &simdnbt::borrow::NbtCompound) -> Result { let value = Self { #(#field_deserializers),* }; @@ -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::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &simdnbt::borrow::NbtTag) -> Option { match tag.string()?.to_str().as_ref() { #(#matchers)* _ => None, diff --git a/simdnbt/examples/hypixel.rs b/simdnbt/examples/hypixel.rs index c0c9d45..63a5772 100644 --- a/simdnbt/examples/hypixel.rs +++ b/simdnbt/examples/hypixel.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, hint::black_box, io::Cursor}; -use simdnbt::{owned::Nbt, Deserialize, Serialize}; +use simdnbt::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct Item { @@ -68,13 +68,18 @@ fn main() { let input = black_box(include_bytes!("../tests/realworld.nbt")); for _ in 0..1 { - let nbt = Nbt::read(&mut Cursor::new(input)); + let nbt = simdnbt::borrow::Nbt::read(&mut Cursor::new(input)); let nbt = black_box(nbt.unwrap().unwrap()); - let data = Base::from_nbt(nbt).unwrap(); + let data = Base::from_nbt(&nbt).unwrap(); // roundtrip - let new_data = Base::from_nbt(data.clone().to_nbt()).unwrap(); + let mut new_nbt_bytes = Vec::new(); + data.clone().to_nbt().write(&mut new_nbt_bytes); + let new_nbt = simdnbt::borrow::Nbt::read(&mut Cursor::new(&new_nbt_bytes[..])) + .unwrap() + .unwrap(); + let new_data = Base::from_nbt(&new_nbt).unwrap(); assert_eq!(data, new_data); println!("data: {:?}", data.items); diff --git a/simdnbt/src/borrow/compound.rs b/simdnbt/src/borrow/compound.rs index f7c39c1..43d9440 100644 --- a/simdnbt/src/borrow/compound.rs +++ b/simdnbt/src/borrow/compound.rs @@ -21,6 +21,10 @@ pub struct NbtCompound<'a> { } impl<'a> NbtCompound<'a> { + pub fn from_values(values: Vec<(&'a Mutf8Str, NbtTag<'a>)>) -> Self { + Self { values } + } + pub fn read(data: &mut Cursor<&'a [u8]>) -> Result { Self::read_with_depth(data, 0) } @@ -204,4 +208,20 @@ impl<'a> NbtCompound<'a> { pub fn iter(&self) -> impl Iterator)> { self.values.iter().map(|(k, v)| (*k, v)) } + pub fn len(&self) -> usize { + self.values.len() + } + pub fn is_empty(&self) -> bool { + self.values.is_empty() + } + + pub fn to_owned(&self) -> crate::owned::NbtCompound { + crate::owned::NbtCompound { + values: self + .values + .iter() + .map(|(k, v)| ((*k).to_owned(), v.to_owned())) + .collect(), + } + } } diff --git a/simdnbt/src/borrow/list.rs b/simdnbt/src/borrow/list.rs index 4f8f321..a1f29aa 100644 --- a/simdnbt/src/borrow/list.rs +++ b/simdnbt/src/borrow/list.rs @@ -265,4 +265,43 @@ impl<'a> NbtList<'a> { _ => None, } } + + pub fn to_owned(&self) -> crate::owned::NbtList { + match self { + NbtList::Empty => crate::owned::NbtList::Empty, + NbtList::Byte(bytes) => crate::owned::NbtList::Byte(bytes.to_vec()), + NbtList::Short(shorts) => crate::owned::NbtList::Short(shorts.to_vec()), + NbtList::Int(ints) => crate::owned::NbtList::Int(ints.to_vec()), + NbtList::Long(longs) => crate::owned::NbtList::Long(longs.to_vec()), + NbtList::Float(floats) => crate::owned::NbtList::Float(floats.to_vec()), + NbtList::Double(doubles) => crate::owned::NbtList::Double(doubles.to_vec()), + NbtList::ByteArray(byte_arrays) => crate::owned::NbtList::ByteArray( + byte_arrays.iter().map(|array| array.to_vec()).collect(), + ), + NbtList::String(strings) => crate::owned::NbtList::String( + strings.iter().map(|&string| string.to_owned()).collect(), + ), + NbtList::List(lists) => { + crate::owned::NbtList::List(lists.iter().map(|list| list.to_owned()).collect()) + } + NbtList::Compound(compounds) => crate::owned::NbtList::Compound( + compounds + .iter() + .map(|compound| compound.to_owned()) + .collect(), + ), + NbtList::IntArray(int_arrays) => crate::owned::NbtList::IntArray( + int_arrays + .iter() + .map(|array| array.to_vec()) + .collect::>(), + ), + NbtList::LongArray(long_arrays) => crate::owned::NbtList::LongArray( + long_arrays + .iter() + .map(|array| array.to_vec()) + .collect::>(), + ), + } + } } diff --git a/simdnbt/src/borrow/mod.rs b/simdnbt/src/borrow/mod.rs index 1eacb19..c2093e9 100644 --- a/simdnbt/src/borrow/mod.rs +++ b/simdnbt/src/borrow/mod.rs @@ -200,6 +200,23 @@ impl<'a> NbtTag<'a> { _ => None, } } + + pub fn to_owned(&self) -> crate::owned::NbtTag { + match self { + NbtTag::Byte(byte) => crate::owned::NbtTag::Byte(*byte), + NbtTag::Short(short) => crate::owned::NbtTag::Short(*short), + NbtTag::Int(int) => crate::owned::NbtTag::Int(*int), + NbtTag::Long(long) => crate::owned::NbtTag::Long(*long), + NbtTag::Float(float) => crate::owned::NbtTag::Float(*float), + NbtTag::Double(double) => crate::owned::NbtTag::Double(*double), + NbtTag::ByteArray(byte_array) => crate::owned::NbtTag::ByteArray(byte_array.to_vec()), + NbtTag::String(string) => crate::owned::NbtTag::String((*string).to_owned()), + NbtTag::List(list) => crate::owned::NbtTag::List(list.to_owned()), + NbtTag::Compound(compound) => crate::owned::NbtTag::Compound(compound.to_owned()), + NbtTag::IntArray(int_array) => crate::owned::NbtTag::IntArray(int_array.to_vec()), + NbtTag::LongArray(long_array) => crate::owned::NbtTag::LongArray(long_array.to_vec()), + } + } } #[cfg(test)] diff --git a/simdnbt/src/traits.rs b/simdnbt/src/traits.rs index bf3a289..606bc93 100644 --- a/simdnbt/src/traits.rs +++ b/simdnbt/src/traits.rs @@ -3,11 +3,11 @@ use std::{collections::HashMap, fmt::Display, hash::Hash, str::FromStr}; use crate::DeserializeError; pub trait Deserialize: Sized { - fn from_nbt(nbt: crate::owned::BaseNbt) -> Result { - Self::from_compound(nbt.into_inner()) + fn from_nbt(nbt: &crate::borrow::BaseNbt) -> Result { + Self::from_compound(nbt) } - fn from_compound(compound: crate::owned::NbtCompound) -> Result; + fn from_compound(compound: &crate::borrow::NbtCompound) -> Result; } pub trait Serialize: Sized { @@ -19,9 +19,9 @@ pub trait Serialize: Sized { } pub trait FromNbtTag: Sized { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option; + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option; fn from_optional_nbt_tag( - tag: Option, + tag: Option<&crate::borrow::NbtTag>, ) -> Result, DeserializeError> { match tag { Some(tag) => Ok(Self::from_nbt_tag(tag)), @@ -38,10 +38,10 @@ pub trait ToNbtTag: Sized { } impl Deserialize for HashMap { - fn from_compound(compound: crate::owned::NbtCompound) -> Result { - let mut hashmap = HashMap::with_capacity(compound.values.len()); + fn from_compound(compound: &crate::borrow::NbtCompound) -> Result { + let mut hashmap = HashMap::with_capacity(compound.len()); - for (k, v) in compound.values { + for (k, v) in compound.iter() { let k_str = k.to_str(); let k_parsed = k_str .parse() @@ -70,8 +70,8 @@ impl Serialize for HashMap } impl Deserialize for crate::owned::NbtCompound { - fn from_compound(compound: crate::owned::NbtCompound) -> Result { - Ok(compound) + fn from_compound(compound: &crate::borrow::NbtCompound) -> Result { + Ok(compound.to_owned()) } } impl Serialize for crate::owned::NbtCompound { @@ -81,9 +81,8 @@ impl Serialize for crate::owned::NbtCompound { } impl FromNbtTag for T { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { - tag.into_compound() - .and_then(|c| Self::from_compound(c).ok()) + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { + tag.compound().and_then(|c| Self::from_compound(c).ok()) } } @@ -94,8 +93,8 @@ impl ToNbtTag for T { } impl FromNbtTag for crate::owned::NbtTag { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { - Some(tag) + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { + Some(tag.to_owned()) } } impl ToNbtTag for crate::owned::NbtTag { @@ -106,7 +105,7 @@ impl ToNbtTag for crate::owned::NbtTag { // standard nbt types impl FromNbtTag for i8 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.byte() } } @@ -117,7 +116,7 @@ impl ToNbtTag for i8 { } impl FromNbtTag for i16 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.short() } } @@ -128,7 +127,7 @@ impl ToNbtTag for i16 { } impl FromNbtTag for i32 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.int() } } @@ -139,7 +138,7 @@ impl ToNbtTag for i32 { } impl FromNbtTag for i64 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.long() } } @@ -150,7 +149,7 @@ impl ToNbtTag for i64 { } impl FromNbtTag for f32 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.float() } } @@ -161,7 +160,7 @@ impl ToNbtTag for f32 { } impl FromNbtTag for f64 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.double() } } @@ -172,7 +171,7 @@ impl ToNbtTag for f64 { } impl FromNbtTag for String { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.string().map(|s| s.to_string()) } } @@ -184,7 +183,7 @@ impl ToNbtTag for String { // unsigned integers impl FromNbtTag for u8 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.byte().map(|b| b as u8) } } @@ -195,7 +194,7 @@ impl ToNbtTag for u8 { } impl FromNbtTag for u16 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.short().map(|s| s as u16) } } @@ -206,7 +205,7 @@ impl ToNbtTag for u16 { } impl FromNbtTag for u32 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.int().map(|i| i as u32) } } @@ -217,7 +216,7 @@ impl ToNbtTag for u32 { } impl FromNbtTag for u64 { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.long().map(|l| l as u64) } } @@ -229,7 +228,7 @@ impl ToNbtTag for u64 { // lists impl FromNbtTag for Vec { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.list().and_then(|l| { l.strings() .map(|s| s.iter().map(|s| s.to_string()).collect()) @@ -246,11 +245,11 @@ impl ToNbtTag for Vec { // slightly less standard types impl FromNbtTag for Option { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { Some(T::from_nbt_tag(tag)) } fn from_optional_nbt_tag( - tag: Option, + tag: Option<&crate::borrow::NbtTag>, ) -> Result, DeserializeError> { match tag { Some(tag) => Ok(Some(T::from_nbt_tag(tag))), @@ -269,11 +268,11 @@ impl ToNbtTag for Option { impl FromNbtTag for Vec> { /// A list of compounds where `None` is an empty compound - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { - let list = tag.into_list()?.into_compounds()?; + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { + let list = tag.list()?.compounds()?; let mut vec = Vec::with_capacity(list.len()); for tag in list { - if tag.values.is_empty() { + if tag.is_empty() { vec.push(None); } else { vec.push(Some(T::from_compound(tag).ok()?)); @@ -297,8 +296,8 @@ impl ToNbtTag for Vec> { } impl FromNbtTag for Vec { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { - let list = tag.into_list()?.into_compounds()?; + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { + let list = tag.list()?.compounds()?; let mut vec = Vec::with_capacity(list.len()); for tag in list { vec.push(T::from_compound(tag).ok()?); @@ -316,7 +315,7 @@ impl ToNbtTag for Vec { } impl FromNbtTag for bool { - fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option { + fn from_nbt_tag(tag: &crate::borrow::NbtTag) -> Option { tag.byte().map(|b| b != 0) } }