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

random polish

This commit is contained in:
mat 2023-09-21 22:51:39 -05:00
commit 1526a21276
7 changed files with 296 additions and 145 deletions

View file

@ -12,16 +12,20 @@ use crate::{
Error, Mutf8Str,
};
use super::{list::ListTag, Tag};
use super::{list::ListTag, NbtTag};
/// A list of named tags. The order of the tags is preserved.
#[derive(Debug, Default, PartialEq)]
pub struct CompoundTag<'a> {
values: Vec<(&'a Mutf8Str, Tag<'a>)>,
pub struct NbtCompound<'a> {
values: Vec<(&'a Mutf8Str, NbtTag<'a>)>,
}
impl<'a> CompoundTag<'a> {
pub fn new(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
impl<'a> NbtCompound<'a> {
pub fn read(data: &mut Cursor<&'a [u8]>) -> Result<Self, Error> {
Self::read_with_depth(data, 0)
}
pub fn read_with_depth(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
if depth > MAX_DEPTH {
return Err(Error::MaxDepthExceeded);
}
@ -36,38 +40,39 @@ impl<'a> CompoundTag<'a> {
match tag_type {
BYTE_ID => values.push((
tag_name,
Tag::Byte(data.read_i8().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Byte(data.read_i8().map_err(|_| Error::UnexpectedEof)?),
)),
SHORT_ID => values.push((
tag_name,
Tag::Short(data.read_i16::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Short(data.read_i16::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
INT_ID => values.push((
tag_name,
Tag::Int(data.read_i32::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Int(data.read_i32::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
LONG_ID => values.push((
tag_name,
Tag::Long(data.read_i64::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Long(data.read_i64::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
FLOAT_ID => values.push((
tag_name,
Tag::Float(data.read_f32::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Float(data.read_f32::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
DOUBLE_ID => values.push((
tag_name,
Tag::Double(data.read_f64::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Double(data.read_f64::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
BYTE_ARRAY_ID => {
values.push((tag_name, Tag::ByteArray(read_with_u32_length(data, 1)?)))
values.push((tag_name, NbtTag::ByteArray(read_with_u32_length(data, 1)?)))
}
STRING_ID => values.push((tag_name, Tag::String(read_string(data)?))),
LIST_ID => values.push((tag_name, Tag::List(ListTag::new(data, depth + 1)?))),
COMPOUND_ID => {
values.push((tag_name, Tag::Compound(CompoundTag::new(data, depth + 1)?)))
}
INT_ARRAY_ID => values.push((tag_name, Tag::IntArray(read_int_array(data)?))),
LONG_ARRAY_ID => values.push((tag_name, Tag::LongArray(read_long_array(data)?))),
STRING_ID => values.push((tag_name, NbtTag::String(read_string(data)?))),
LIST_ID => values.push((tag_name, NbtTag::List(ListTag::read(data, depth + 1)?))),
COMPOUND_ID => values.push((
tag_name,
NbtTag::Compound(NbtCompound::read_with_depth(data, depth + 1)?),
)),
INT_ARRAY_ID => values.push((tag_name, NbtTag::IntArray(read_int_array(data)?))),
LONG_ARRAY_ID => values.push((tag_name, NbtTag::LongArray(read_long_array(data)?))),
_ => return Err(Error::UnknownTagId(tag_type)),
}
}
@ -85,46 +90,46 @@ impl<'a> CompoundTag<'a> {
unchecked_write_string(data, name);
}
match tag {
Tag::Byte(byte) => unsafe {
NbtTag::Byte(byte) => unsafe {
unchecked_push(data, *byte as u8);
},
Tag::Short(short) => unsafe {
NbtTag::Short(short) => unsafe {
unchecked_extend(data, &short.to_be_bytes());
},
Tag::Int(int) => unsafe {
NbtTag::Int(int) => unsafe {
unchecked_extend(data, &int.to_be_bytes());
},
Tag::Long(long) => {
NbtTag::Long(long) => {
data.extend_from_slice(&long.to_be_bytes());
}
Tag::Float(float) => unsafe {
NbtTag::Float(float) => unsafe {
unchecked_extend(data, &float.to_be_bytes());
},
Tag::Double(double) => {
NbtTag::Double(double) => {
data.extend_from_slice(&double.to_be_bytes());
}
Tag::ByteArray(byte_array) => {
NbtTag::ByteArray(byte_array) => {
unsafe {
unchecked_extend(data, &byte_array.len().to_be_bytes());
}
data.extend_from_slice(byte_array);
}
Tag::String(string) => {
NbtTag::String(string) => {
write_string(data, string);
}
Tag::List(list) => {
NbtTag::List(list) => {
list.write(data);
}
Tag::Compound(compound) => {
NbtTag::Compound(compound) => {
compound.write(data);
}
Tag::IntArray(int_array) => {
NbtTag::IntArray(int_array) => {
unsafe {
unchecked_extend(data, &int_array.len().to_be_bytes());
}
data.extend_from_slice(&int_array.as_big_endian());
}
Tag::LongArray(long_array) => {
NbtTag::LongArray(long_array) => {
unsafe {
unchecked_extend(data, &long_array.len().to_be_bytes());
}
@ -136,7 +141,7 @@ impl<'a> CompoundTag<'a> {
}
#[inline]
pub fn get(&self, name: &str) -> Option<&Tag<'a>> {
pub fn get(&self, name: &str) -> Option<&NbtTag<'a>> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
@ -186,7 +191,7 @@ impl<'a> CompoundTag<'a> {
pub fn list(&self, name: &str) -> Option<&ListTag<'a>> {
self.get(name).and_then(|tag| tag.list())
}
pub fn compound(&self, name: &str) -> Option<&CompoundTag<'a>> {
pub fn compound(&self, name: &str) -> Option<&NbtCompound<'a>> {
self.get(name).and_then(|tag| tag.compound())
}
pub fn int_array(&self, name: &str) -> Option<Vec<i32>> {
@ -196,7 +201,7 @@ impl<'a> CompoundTag<'a> {
self.get(name).and_then(|tag| tag.long_array())
}
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &Tag<'a>)> {
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &NbtTag<'a>)> {
self.values.iter().map(|(k, v)| (*k, v))
}
}

View file

@ -13,7 +13,7 @@ use crate::{
Error, Mutf8Str,
};
use super::{read_u32, CompoundTag, MAX_DEPTH};
use super::{read_u32, NbtCompound, MAX_DEPTH};
/// A list of NBT tags of a single type.
#[repr(u8)]
@ -30,12 +30,12 @@ pub enum ListTag<'a> {
ByteArray(Vec<&'a [u8]>) = BYTE_ARRAY_ID,
String(Vec<&'a Mutf8Str>) = STRING_ID,
List(Vec<ListTag<'a>>) = LIST_ID,
Compound(Vec<CompoundTag<'a>>) = COMPOUND_ID,
Compound(Vec<NbtCompound<'a>>) = COMPOUND_ID,
IntArray(Vec<RawList<'a, i32>>) = INT_ARRAY_ID,
LongArray(Vec<RawList<'a, i64>>) = LONG_ARRAY_ID,
}
impl<'a> ListTag<'a> {
pub fn new(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
pub fn read(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
if depth > MAX_DEPTH {
return Err(Error::MaxDepthExceeded);
}
@ -74,7 +74,7 @@ impl<'a> ListTag<'a> {
// arbitrary number to prevent big allocations
let mut lists = Vec::with_capacity(length.min(128) as usize);
for _ in 0..length {
lists.push(ListTag::new(data, depth + 1)?)
lists.push(ListTag::read(data, depth + 1)?)
}
lists
}),
@ -83,7 +83,7 @@ impl<'a> ListTag<'a> {
// arbitrary number to prevent big allocations
let mut compounds = Vec::with_capacity(length.min(128) as usize);
for _ in 0..length {
compounds.push(CompoundTag::new(data, depth + 1)?)
compounds.push(NbtCompound::read_with_depth(data, depth + 1)?)
}
compounds
}),
@ -247,7 +247,7 @@ impl<'a> ListTag<'a> {
_ => None,
}
}
pub fn compounds(&self) -> Option<&[CompoundTag]> {
pub fn compounds(&self) -> Option<&[NbtCompound]> {
match self {
ListTag::Compound(compounds) => Some(compounds),
_ => None,

View file

@ -17,13 +17,13 @@ use crate::{
Error, Mutf8Str,
};
pub use self::{compound::CompoundTag, list::ListTag};
pub use self::{compound::NbtCompound, list::ListTag};
/// A complete NBT container. This contains a name and a compound tag.
#[derive(Debug, PartialEq)]
pub struct BaseNbt<'a> {
name: &'a Mutf8Str,
tag: CompoundTag<'a>,
tag: NbtCompound<'a>,
}
#[derive(Debug, PartialEq)]
@ -43,7 +43,7 @@ impl<'a> Nbt<'a> {
return Err(Error::InvalidRootType(root_type));
}
let name = read_string(data)?;
let tag = CompoundTag::new(data, 0)?;
let tag = NbtCompound::read_with_depth(data, 0)?;
Ok(Nbt::Some(BaseNbt { name, tag }))
}
@ -83,7 +83,7 @@ impl<'a> BaseNbt<'a> {
}
}
impl<'a> Deref for BaseNbt<'a> {
type Target = CompoundTag<'a>;
type Target = NbtCompound<'a>;
fn deref(&self) -> &Self::Target {
&self.tag
@ -102,7 +102,7 @@ impl<'a> BaseNbt<'a> {
/// A single NBT tag.
#[repr(u8)]
#[derive(Debug, PartialEq)]
pub enum Tag<'a> {
pub enum NbtTag<'a> {
Byte(i8) = BYTE_ID,
Short(i16) = SHORT_ID,
Int(i32) = INT_ID,
@ -112,11 +112,11 @@ pub enum Tag<'a> {
ByteArray(&'a [u8]) = BYTE_ARRAY_ID,
String(&'a Mutf8Str) = STRING_ID,
List(ListTag<'a>) = LIST_ID,
Compound(CompoundTag<'a>) = COMPOUND_ID,
Compound(NbtCompound<'a>) = COMPOUND_ID,
IntArray(RawList<'a, i32>) = INT_ARRAY_ID,
LongArray(RawList<'a, i64>) = LONG_ARRAY_ID,
}
impl<'a> Tag<'a> {
impl<'a> NbtTag<'a> {
/// Get the numerical ID of the tag type.
#[inline]
pub fn id(&self) -> u8 {
@ -129,73 +129,73 @@ impl<'a> Tag<'a> {
pub fn byte(&self) -> Option<i8> {
match self {
Tag::Byte(byte) => Some(*byte),
NbtTag::Byte(byte) => Some(*byte),
_ => None,
}
}
pub fn short(&self) -> Option<i16> {
match self {
Tag::Short(short) => Some(*short),
NbtTag::Short(short) => Some(*short),
_ => None,
}
}
pub fn int(&self) -> Option<i32> {
match self {
Tag::Int(int) => Some(*int),
NbtTag::Int(int) => Some(*int),
_ => None,
}
}
pub fn long(&self) -> Option<i64> {
match self {
Tag::Long(long) => Some(*long),
NbtTag::Long(long) => Some(*long),
_ => None,
}
}
pub fn float(&self) -> Option<f32> {
match self {
Tag::Float(float) => Some(*float),
NbtTag::Float(float) => Some(*float),
_ => None,
}
}
pub fn double(&self) -> Option<f64> {
match self {
Tag::Double(double) => Some(*double),
NbtTag::Double(double) => Some(*double),
_ => None,
}
}
pub fn byte_array(&self) -> Option<&[u8]> {
match self {
Tag::ByteArray(byte_array) => Some(byte_array),
NbtTag::ByteArray(byte_array) => Some(byte_array),
_ => None,
}
}
pub fn string(&self) -> Option<&Mutf8Str> {
match self {
Tag::String(string) => Some(string),
NbtTag::String(string) => Some(string),
_ => None,
}
}
pub fn list(&self) -> Option<&ListTag<'a>> {
match self {
Tag::List(list) => Some(list),
NbtTag::List(list) => Some(list),
_ => None,
}
}
pub fn compound(&self) -> Option<&CompoundTag<'a>> {
pub fn compound(&self) -> Option<&NbtCompound<'a>> {
match self {
Tag::Compound(compound) => Some(compound),
NbtTag::Compound(compound) => Some(compound),
_ => None,
}
}
pub fn int_array(&self) -> Option<Vec<i32>> {
match self {
Tag::IntArray(int_array) => Some(int_array.to_vec()),
NbtTag::IntArray(int_array) => Some(int_array.to_vec()),
_ => None,
}
}
pub fn long_array(&self) -> Option<Vec<i64>> {
match self {
Tag::LongArray(long_array) => Some(long_array.to_vec()),
NbtTag::LongArray(long_array) => Some(long_array.to_vec()),
_ => None,
}
}

View file

@ -15,7 +15,7 @@ pub struct Mutf8Str {
/// An owned M-UTF8 string.
#[derive(Debug, Eq, PartialEq, Clone, Default)]
pub struct Mutf8String {
vec: Vec<u8>,
pub(crate) vec: Vec<u8>,
}
#[inline]
@ -168,6 +168,16 @@ impl Mutf8String {
pub fn len(&self) -> usize {
self.vec.len()
}
#[inline]
pub fn from_vec(vec: Vec<u8>) -> Mutf8String {
Self { vec }
}
#[inline]
pub fn from_string(s: String) -> Mutf8String {
Self::from_vec(mutf8::encode(&s).into_owned())
}
}
impl Deref for Mutf8String {
type Target = Mutf8Str;
@ -178,7 +188,12 @@ impl Deref for Mutf8String {
}
}
// TODO: make Mutf8 correct
impl From<String> for Mutf8String {
#[inline]
fn from(s: String) -> Self {
Self::from_string(s)
}
}
#[cfg(test)]
mod tests {

View file

@ -13,16 +13,24 @@ use crate::{
Error, Mutf8Str,
};
use super::{list::ListTag, Tag};
use super::{list::ListTag, NbtTag};
/// A list of named tags. The order of the tags is preserved.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct CompoundTag {
values: Vec<(Mutf8String, Tag)>,
pub struct NbtCompound {
pub(crate) values: Vec<(Mutf8String, NbtTag)>,
}
impl CompoundTag {
pub fn new(data: &mut Cursor<&[u8]>, depth: usize) -> Result<Self, Error> {
impl NbtCompound {
pub fn new() -> Self {
Self::default()
}
pub fn read(data: &mut Cursor<&[u8]>) -> Result<Self, Error> {
Self::read_with_depth(data, 0)
}
pub fn read_with_depth(data: &mut Cursor<&[u8]>, depth: usize) -> Result<Self, Error> {
if depth > MAX_DEPTH {
return Err(Error::MaxDepthExceeded);
}
@ -37,42 +45,43 @@ impl CompoundTag {
match tag_type {
BYTE_ID => values.push((
tag_name,
Tag::Byte(data.read_i8().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Byte(data.read_i8().map_err(|_| Error::UnexpectedEof)?),
)),
SHORT_ID => values.push((
tag_name,
Tag::Short(data.read_i16::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Short(data.read_i16::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
INT_ID => values.push((
tag_name,
Tag::Int(data.read_i32::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Int(data.read_i32::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
LONG_ID => values.push((
tag_name,
Tag::Long(data.read_i64::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Long(data.read_i64::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
FLOAT_ID => values.push((
tag_name,
Tag::Float(data.read_f32::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Float(data.read_f32::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
DOUBLE_ID => values.push((
tag_name,
Tag::Double(data.read_f64::<BE>().map_err(|_| Error::UnexpectedEof)?),
NbtTag::Double(data.read_f64::<BE>().map_err(|_| Error::UnexpectedEof)?),
)),
BYTE_ARRAY_ID => values.push((
tag_name,
Tag::ByteArray(read_with_u32_length(data, 1)?.to_owned()),
NbtTag::ByteArray(read_with_u32_length(data, 1)?.to_owned()),
)),
STRING_ID => values.push((tag_name, NbtTag::String(read_string(data)?.to_owned()))),
LIST_ID => values.push((tag_name, NbtTag::List(ListTag::read(data, depth + 1)?))),
COMPOUND_ID => values.push((
tag_name,
NbtTag::Compound(NbtCompound::read_with_depth(data, depth + 1)?),
)),
STRING_ID => values.push((tag_name, Tag::String(read_string(data)?.to_owned()))),
LIST_ID => values.push((tag_name, Tag::List(ListTag::new(data, depth + 1)?))),
COMPOUND_ID => {
values.push((tag_name, Tag::Compound(CompoundTag::new(data, depth + 1)?)))
}
INT_ARRAY_ID => {
values.push((tag_name, Tag::IntArray(read_int_array(data)?.to_vec())))
values.push((tag_name, NbtTag::IntArray(read_int_array(data)?.to_vec())))
}
LONG_ARRAY_ID => {
values.push((tag_name, Tag::LongArray(read_long_array(data)?.to_vec())))
values.push((tag_name, NbtTag::LongArray(read_long_array(data)?.to_vec())))
}
_ => return Err(Error::UnknownTagId(tag_type)),
}
@ -91,46 +100,46 @@ impl CompoundTag {
unchecked_write_string(data, name);
}
match tag {
Tag::Byte(byte) => unsafe {
NbtTag::Byte(byte) => unsafe {
unchecked_push(data, *byte as u8);
},
Tag::Short(short) => unsafe {
NbtTag::Short(short) => unsafe {
unchecked_extend(data, &short.to_be_bytes());
},
Tag::Int(int) => unsafe {
NbtTag::Int(int) => unsafe {
unchecked_extend(data, &int.to_be_bytes());
},
Tag::Long(long) => {
NbtTag::Long(long) => {
data.extend_from_slice(&long.to_be_bytes());
}
Tag::Float(float) => unsafe {
NbtTag::Float(float) => unsafe {
unchecked_extend(data, &float.to_be_bytes());
},
Tag::Double(double) => {
NbtTag::Double(double) => {
data.extend_from_slice(&double.to_be_bytes());
}
Tag::ByteArray(byte_array) => {
NbtTag::ByteArray(byte_array) => {
unsafe {
unchecked_extend(data, &byte_array.len().to_be_bytes());
}
data.extend_from_slice(byte_array);
}
Tag::String(string) => {
NbtTag::String(string) => {
write_string(data, string);
}
Tag::List(list) => {
NbtTag::List(list) => {
list.write(data);
}
Tag::Compound(compound) => {
NbtTag::Compound(compound) => {
compound.write(data);
}
Tag::IntArray(int_array) => {
NbtTag::IntArray(int_array) => {
unsafe {
unchecked_extend(data, &int_array.len().to_be_bytes());
}
data.extend_from_slice(&slice_into_u8_big_endian(int_array));
}
Tag::LongArray(long_array) => {
NbtTag::LongArray(long_array) => {
unsafe {
unchecked_extend(data, &long_array.len().to_be_bytes());
}
@ -142,7 +151,7 @@ impl CompoundTag {
}
#[inline]
pub fn get(&self, name: &str) -> Option<&Tag> {
pub fn get(&self, name: &str) -> Option<&NbtTag> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &self.values {
@ -154,7 +163,7 @@ impl CompoundTag {
}
#[inline]
pub fn get_mut(&mut self, name: &str) -> Option<&mut Tag> {
pub fn get_mut(&mut self, name: &str) -> Option<&mut NbtTag> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for (key, value) in &mut self.values {
@ -231,10 +240,10 @@ impl CompoundTag {
pub fn list_mut(&mut self, name: &str) -> Option<&mut ListTag> {
self.get_mut(name).and_then(|tag| tag.list_mut())
}
pub fn compound(&self, name: &str) -> Option<&CompoundTag> {
pub fn compound(&self, name: &str) -> Option<&NbtCompound> {
self.get(name).and_then(|tag| tag.compound())
}
pub fn compound_mut(&mut self, name: &str) -> Option<&mut CompoundTag> {
pub fn compound_mut(&mut self, name: &str) -> Option<&mut NbtCompound> {
self.get_mut(name).and_then(|tag| tag.compound_mut())
}
pub fn int_array(&self, name: &str) -> Option<&[i32]> {
@ -250,10 +259,10 @@ impl CompoundTag {
self.get_mut(name).and_then(|tag| tag.long_array_mut())
}
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &Tag)> {
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &NbtTag)> {
self.values.iter().map(|(k, v)| (k.as_str(), v))
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Mutf8Str, &mut Tag)> {
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&Mutf8Str, &mut NbtTag)> {
self.values.iter_mut().map(|(k, v)| (k.as_str(), v))
}
pub fn len(&self) -> usize {
@ -268,22 +277,23 @@ impl CompoundTag {
pub fn keys_mut(&mut self) -> impl Iterator<Item = &mut Mutf8String> {
self.values.iter_mut().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &Tag> {
pub fn values(&self) -> impl Iterator<Item = &NbtTag> {
self.values.iter().map(|(_, v)| v)
}
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut Tag> {
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut NbtTag> {
self.values.iter_mut().map(|(_, v)| v)
}
pub fn into_iter(self) -> impl Iterator<Item = (Mutf8String, Tag)> {
pub fn into_iter(self) -> impl Iterator<Item = (Mutf8String, NbtTag)> {
self.values.into_iter()
}
pub fn clear(&mut self) {
self.values.clear();
}
pub fn insert(&mut self, name: Mutf8String, tag: Tag) {
pub fn insert(&mut self, name: impl Into<Mutf8String>, tag: NbtTag) {
let name = name.into();
self.values.push((name, tag));
}
pub fn remove(&mut self, name: &str) -> Option<Tag> {
pub fn remove(&mut self, name: &str) -> Option<NbtTag> {
let name = Mutf8Str::from_str(name);
let name = name.as_ref();
for i in 0..self.values.len() {

View file

@ -15,7 +15,7 @@ use crate::{
Error,
};
use super::{compound::CompoundTag, read_u32, MAX_DEPTH};
use super::{compound::NbtCompound, read_u32, MAX_DEPTH};
/// A list of NBT tags of a single type.
#[repr(u8)]
@ -32,12 +32,12 @@ pub enum ListTag {
ByteArray(Vec<Vec<u8>>) = BYTE_ARRAY_ID,
String(Vec<Mutf8String>) = STRING_ID,
List(Vec<ListTag>) = LIST_ID,
Compound(Vec<CompoundTag>) = COMPOUND_ID,
Compound(Vec<NbtCompound>) = COMPOUND_ID,
IntArray(Vec<Vec<i32>>) = INT_ARRAY_ID,
LongArray(Vec<Vec<i64>>) = LONG_ARRAY_ID,
}
impl ListTag {
pub fn new(data: &mut Cursor<&[u8]>, depth: usize) -> Result<Self, Error> {
pub fn read(data: &mut Cursor<&[u8]>, depth: usize) -> Result<Self, Error> {
if depth > MAX_DEPTH {
return Err(Error::MaxDepthExceeded);
}
@ -76,7 +76,7 @@ impl ListTag {
// arbitrary number to prevent big allocations
let mut lists = Vec::with_capacity(length.min(128) as usize);
for _ in 0..length {
lists.push(ListTag::new(data, depth + 1)?)
lists.push(ListTag::read(data, depth + 1)?)
}
lists
}),
@ -85,7 +85,7 @@ impl ListTag {
// arbitrary number to prevent big allocations
let mut compounds = Vec::with_capacity(length.min(128) as usize);
for _ in 0..length {
compounds.push(CompoundTag::new(data, depth + 1)?)
compounds.push(NbtCompound::read_with_depth(data, depth + 1)?)
}
compounds
}),
@ -249,7 +249,7 @@ impl ListTag {
_ => None,
}
}
pub fn compounds(&self) -> Option<&[CompoundTag]> {
pub fn compounds(&self) -> Option<&[NbtCompound]> {
match self {
ListTag::Compound(compounds) => Some(compounds),
_ => None,

View file

@ -17,13 +17,13 @@ use crate::{
Error, Mutf8Str,
};
pub use self::{compound::CompoundTag, list::ListTag};
pub use self::{compound::NbtCompound, list::ListTag};
/// A complete NBT container. This contains a name and a compound tag.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct BaseNbt {
name: Mutf8String,
tag: CompoundTag,
tag: NbtCompound,
}
#[derive(Debug, Clone, PartialEq)]
@ -33,7 +33,7 @@ pub enum Nbt {
}
impl Nbt {
pub fn new(name: Mutf8String, tag: CompoundTag) -> Self {
pub fn new(name: Mutf8String, tag: NbtCompound) -> Self {
Self::Some(BaseNbt { name, tag })
}
@ -47,7 +47,7 @@ impl Nbt {
return Err(Error::InvalidRootType(root_type));
}
let name = read_string(data)?.to_owned();
let tag = CompoundTag::new(data, 0)?;
let tag = NbtCompound::read_with_depth(data, 0)?;
Ok(Nbt::Some(BaseNbt { name, tag }))
}
@ -78,10 +78,44 @@ impl Nbt {
pub fn is_none(&self) -> bool {
!self.is_some()
}
pub fn iter(&self) -> impl Iterator<Item = (&Mutf8Str, &NbtTag)> {
const EMPTY: &'static NbtCompound = &NbtCompound { values: Vec::new() };
if let Nbt::Some(nbt) = self {
nbt.iter()
} else {
EMPTY.iter()
}
}
pub fn into_iter(self) -> impl Iterator<Item = (Mutf8String, NbtTag)> {
const EMPTY: NbtCompound = NbtCompound { values: Vec::new() };
match self {
Nbt::Some(nbt) => nbt.tag.into_iter(),
Nbt::None => EMPTY.into_iter(),
}
}
}
impl Deref for Nbt {
type Target = BaseNbt;
fn deref(&self) -> &Self::Target {
const EMPTY: &'static BaseNbt = &BaseNbt {
name: Mutf8String { vec: Vec::new() },
tag: NbtCompound { values: Vec::new() },
};
match self {
Nbt::Some(nbt) => nbt,
Nbt::None => EMPTY,
}
}
}
impl BaseNbt {
pub fn new(name: Mutf8String, tag: CompoundTag) -> Self {
pub fn new(name: Mutf8String, tag: NbtCompound) -> Self {
Self { name, tag }
}
@ -96,9 +130,13 @@ impl BaseNbt {
write_string(data, &self.name);
self.tag.write(data);
}
pub fn into_iter(self) -> impl Iterator<Item = (Mutf8String, NbtTag)> {
self.tag.into_iter()
}
}
impl Deref for BaseNbt {
type Target = CompoundTag;
type Target = NbtCompound;
fn deref(&self) -> &Self::Target {
&self.tag
@ -108,7 +146,7 @@ impl Deref for BaseNbt {
/// A single NBT tag.
#[repr(u8)]
#[derive(Debug, Clone, PartialEq)]
pub enum Tag {
pub enum NbtTag {
Byte(i8) = BYTE_ID,
Short(i16) = SHORT_ID,
Int(i32) = INT_ID,
@ -118,11 +156,11 @@ pub enum Tag {
ByteArray(Vec<u8>) = BYTE_ARRAY_ID,
String(Mutf8String) = STRING_ID,
List(ListTag) = LIST_ID,
Compound(CompoundTag) = COMPOUND_ID,
Compound(NbtCompound) = COMPOUND_ID,
IntArray(Vec<i32>) = INT_ARRAY_ID,
LongArray(Vec<i64>) = LONG_ARRAY_ID,
}
impl Tag {
impl NbtTag {
/// Get the numerical ID of the tag type.
#[inline]
pub fn id(&self) -> u8 {
@ -135,145 +173,228 @@ impl Tag {
pub fn byte(&self) -> Option<i8> {
match self {
Tag::Byte(byte) => Some(*byte),
NbtTag::Byte(byte) => Some(*byte),
_ => None,
}
}
pub fn byte_mut(&mut self) -> Option<&mut i8> {
match self {
Tag::Byte(byte) => Some(byte),
NbtTag::Byte(byte) => Some(byte),
_ => None,
}
}
pub fn into_byte(self) -> Option<i8> {
match self {
NbtTag::Byte(byte) => Some(byte),
_ => None,
}
}
pub fn short(&self) -> Option<i16> {
match self {
Tag::Short(short) => Some(*short),
NbtTag::Short(short) => Some(*short),
_ => None,
}
}
pub fn short_mut(&mut self) -> Option<&mut i16> {
match self {
Tag::Short(short) => Some(short),
NbtTag::Short(short) => Some(short),
_ => None,
}
}
pub fn into_short(self) -> Option<i16> {
match self {
NbtTag::Short(short) => Some(short),
_ => None,
}
}
pub fn int(&self) -> Option<i32> {
match self {
Tag::Int(int) => Some(*int),
NbtTag::Int(int) => Some(*int),
_ => None,
}
}
pub fn int_mut(&mut self) -> Option<&mut i32> {
match self {
Tag::Int(int) => Some(int),
NbtTag::Int(int) => Some(int),
_ => None,
}
}
pub fn into_int(self) -> Option<i32> {
match self {
NbtTag::Int(int) => Some(int),
_ => None,
}
}
pub fn long(&self) -> Option<i64> {
match self {
Tag::Long(long) => Some(*long),
NbtTag::Long(long) => Some(*long),
_ => None,
}
}
pub fn long_mut(&mut self) -> Option<&mut i64> {
match self {
Tag::Long(long) => Some(long),
NbtTag::Long(long) => Some(long),
_ => None,
}
}
pub fn into_long(self) -> Option<i64> {
match self {
NbtTag::Long(long) => Some(long),
_ => None,
}
}
pub fn float(&self) -> Option<f32> {
match self {
Tag::Float(float) => Some(*float),
NbtTag::Float(float) => Some(*float),
_ => None,
}
}
pub fn float_mut(&mut self) -> Option<&mut f32> {
match self {
Tag::Float(float) => Some(float),
NbtTag::Float(float) => Some(float),
_ => None,
}
}
pub fn into_float(self) -> Option<f32> {
match self {
NbtTag::Float(float) => Some(float),
_ => None,
}
}
pub fn double(&self) -> Option<f64> {
match self {
Tag::Double(double) => Some(*double),
NbtTag::Double(double) => Some(*double),
_ => None,
}
}
pub fn double_mut(&mut self) -> Option<&mut f64> {
match self {
Tag::Double(double) => Some(double),
NbtTag::Double(double) => Some(double),
_ => None,
}
}
pub fn into_double(self) -> Option<f64> {
match self {
NbtTag::Double(double) => Some(double),
_ => None,
}
}
pub fn byte_array(&self) -> Option<&[u8]> {
match self {
Tag::ByteArray(byte_array) => Some(byte_array),
NbtTag::ByteArray(byte_array) => Some(byte_array),
_ => None,
}
}
pub fn byte_array_mut(&mut self) -> Option<&mut Vec<u8>> {
match self {
Tag::ByteArray(byte_array) => Some(byte_array),
NbtTag::ByteArray(byte_array) => Some(byte_array),
_ => None,
}
}
pub fn into_byte_array(self) -> Option<Vec<u8>> {
match self {
NbtTag::ByteArray(byte_array) => Some(byte_array),
_ => None,
}
}
pub fn string(&self) -> Option<&Mutf8Str> {
match self {
Tag::String(string) => Some(string),
NbtTag::String(string) => Some(string),
_ => None,
}
}
pub fn string_mut(&mut self) -> Option<&mut Mutf8String> {
match self {
Tag::String(string) => Some(string),
NbtTag::String(string) => Some(string),
_ => None,
}
}
pub fn into_string(self) -> Option<Mutf8String> {
match self {
NbtTag::String(string) => Some(string),
_ => None,
}
}
pub fn list(&self) -> Option<&ListTag> {
match self {
Tag::List(list) => Some(list),
NbtTag::List(list) => Some(list),
_ => None,
}
}
pub fn list_mut(&mut self) -> Option<&mut ListTag> {
match self {
Tag::List(list) => Some(list),
NbtTag::List(list) => Some(list),
_ => None,
}
}
pub fn compound(&self) -> Option<&CompoundTag> {
pub fn into_list(self) -> Option<ListTag> {
match self {
Tag::Compound(compound) => Some(compound),
NbtTag::List(list) => Some(list),
_ => None,
}
}
pub fn compound_mut(&mut self) -> Option<&mut CompoundTag> {
pub fn compound(&self) -> Option<&NbtCompound> {
match self {
Tag::Compound(compound) => Some(compound),
NbtTag::Compound(compound) => Some(compound),
_ => None,
}
}
pub fn compound_mut(&mut self) -> Option<&mut NbtCompound> {
match self {
NbtTag::Compound(compound) => Some(compound),
_ => None,
}
}
pub fn into_compound(self) -> Option<NbtCompound> {
match self {
NbtTag::Compound(compound) => Some(compound),
_ => None,
}
}
pub fn int_array(&self) -> Option<&[i32]> {
match self {
Tag::IntArray(int_array) => Some(int_array),
NbtTag::IntArray(int_array) => Some(int_array),
_ => None,
}
}
pub fn int_array_mut(&mut self) -> Option<&mut Vec<i32>> {
match self {
Tag::IntArray(int_array) => Some(int_array),
NbtTag::IntArray(int_array) => Some(int_array),
_ => None,
}
}
pub fn into_int_array(self) -> Option<Vec<i32>> {
match self {
NbtTag::IntArray(int_array) => Some(int_array),
_ => None,
}
}
pub fn long_array(&self) -> Option<&[i64]> {
match self {
Tag::LongArray(long_array) => Some(long_array),
NbtTag::LongArray(long_array) => Some(long_array),
_ => None,
}
}
pub fn long_array_mut(&mut self) -> Option<&mut Vec<i64>> {
match self {
Tag::LongArray(long_array) => Some(long_array),
NbtTag::LongArray(long_array) => Some(long_array),
_ => None,
}
}
pub fn into_long_array(self) -> Option<Vec<i64>> {
match self {
NbtTag::LongArray(long_array) => Some(long_array),
_ => None,
}
}