mirror of
https://github.com/azalea-rs/simdnbt.git
synced 2025-08-02 07:26:04 +00:00
derive macro
This commit is contained in:
parent
1526a21276
commit
7d4b7b9a22
36 changed files with 1564 additions and 155 deletions
50
Cargo.toml
50
Cargo.toml
|
@ -1,47 +1,3 @@
|
|||
[package]
|
||||
name = "simdnbt"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
description = "an unnecessarily fast nbt decoder"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/mat-1/simdnbt"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.4.3"
|
||||
flate2 = "^1.0.27"
|
||||
residua-mutf8 = "2.0.0"
|
||||
thiserror = "1.0.47"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "^0.5.1", features = ["html_reports"] }
|
||||
graphite_binary = "0.1.0"
|
||||
valence_nbt = { version = "0.6.1", features = ["binary"] }
|
||||
fastnbt = "2.4.4"
|
||||
azalea-nbt = { git = "https://github.com/mat-1/azalea" }
|
||||
hematite-nbt = { version = "0.5.2", default-features = false }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
debug = false
|
||||
|
||||
[profile.bench]
|
||||
lto = true
|
||||
debug = false
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "nbt"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "compare"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "compare_realworld"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "mutf8"
|
||||
[workspace]
|
||||
members = ["simdnbt", "simdnbt-derive"]
|
||||
resolver = "2"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# simdnbt
|
||||
|
||||
an unnecessarily fast nbt decoder. like seriously you probably don't need this unless you're trying to win benchmarks.
|
||||
a very fast nbt serializer and deserializer.
|
||||
|
||||
simdnbt currently makes use of simd instructions for two things:
|
||||
- swapping the endianness of int arrays
|
||||
|
|
14
simdnbt-derive/Cargo.toml
Normal file
14
simdnbt-derive/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "simdnbt-derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.69"
|
||||
quote = "1.0.33"
|
||||
syn = "2.0.38"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
42
simdnbt-derive/src/attrs.rs
Normal file
42
simdnbt-derive/src/attrs.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use syn::parse::{Parse, ParseStream};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct FieldAttrs {
|
||||
pub rename: Option<String>,
|
||||
}
|
||||
|
||||
impl Parse for FieldAttrs {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let mut attrs = Self::default();
|
||||
|
||||
while !input.is_empty() {
|
||||
let attr = input.parse::<proc_macro2::Ident>()?;
|
||||
match attr.to_string().as_str() {
|
||||
"rename" => {
|
||||
input.parse::<syn::Token![=]>()?;
|
||||
let rename = input.parse::<syn::LitStr>()?;
|
||||
|
||||
attrs.rename = Some(rename.value());
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_field_attrs(attrs: &[syn::Attribute]) -> FieldAttrs {
|
||||
let mut field_attrs = FieldAttrs::default();
|
||||
|
||||
for attr in attrs.iter().filter(|attr| attr.path().is_ident("simdnbt")) {
|
||||
let new_attr = attr
|
||||
.parse_args::<FieldAttrs>()
|
||||
.expect("invalid simdnbt attr");
|
||||
if let Some(rename) = new_attr.rename {
|
||||
field_attrs.rename = Some(rename);
|
||||
}
|
||||
}
|
||||
|
||||
field_attrs
|
||||
}
|
53
simdnbt-derive/src/lib.rs
Normal file
53
simdnbt-derive/src/lib.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
mod attrs;
|
||||
|
||||
use attrs::parse_field_attrs;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(simdnbt))]
|
||||
pub fn deserialize_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let ident = input.ident;
|
||||
|
||||
let mut field_deserializers = Vec::<proc_macro2::TokenStream>::new();
|
||||
|
||||
match input.data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||
syn::Fields::Named(syn::FieldsNamed { named, .. }) => {
|
||||
for field in named {
|
||||
let struct_field_name = field.ident.unwrap();
|
||||
|
||||
let mut field_attrs = parse_field_attrs(&field.attrs);
|
||||
|
||||
let field_name = field_attrs
|
||||
.rename
|
||||
.take()
|
||||
.unwrap_or_else(|| struct_field_name.to_string());
|
||||
|
||||
field_deserializers.push(quote! {
|
||||
#struct_field_name: simdnbt::FromNbtTag::from_optional_nbt_tag(
|
||||
nbt.take(#field_name)
|
||||
)?.ok_or(simdnbt::DeserializeError::MismatchedFieldType)?
|
||||
});
|
||||
}
|
||||
}
|
||||
syn::Fields::Unnamed(_) => todo!(),
|
||||
syn::Fields::Unit => todo!(),
|
||||
},
|
||||
syn::Data::Enum(_) => todo!(),
|
||||
syn::Data::Union(_) => todo!(),
|
||||
}
|
||||
|
||||
let output = quote! {
|
||||
impl simdnbt::Deserialize for #ident {
|
||||
fn from_compound(mut nbt: simdnbt::owned::NbtCompound) -> Result<Self, simdnbt::DeserializeError> {
|
||||
Ok(Self {
|
||||
#(#field_deserializers),*
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
output.into()
|
||||
}
|
952
simdnbt/Cargo.lock
generated
Normal file
952
simdnbt/Cargo.lock
generated
Normal file
|
@ -0,0 +1,952 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "azalea-buf"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/mat-1/azalea#5977f79400e46de6a7af413a51bc1afd8e0dc9f6"
|
||||
dependencies = [
|
||||
"azalea-buf-macros",
|
||||
"byteorder",
|
||||
"log",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-buf-macros"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/mat-1/azalea#5977f79400e46de6a7af413a51bc1afd8e0dc9f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-nbt"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/mat-1/azalea#5977f79400e46de6a7af413a51bc1afd8e0dc9f6"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"byteorder",
|
||||
"compact_str",
|
||||
"enum-as-inner",
|
||||
"flate2",
|
||||
"log",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "castaway"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cesu8"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
||||
dependencies = [
|
||||
"castaway",
|
||||
"cfg-if",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastnbt"
|
||||
version = "2.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3369bd70629bccfda7e344883c9ae3ab7f3b10a357bcf8b0f69caa7256bcf188"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cesu8",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphite_binary"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dc8b44c673c50a2b3e6ec6652b8c8d26532254a3a182cc43b76d1b6e4cd1572"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
"cesu8",
|
||||
"graphite_binary_macros",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphite_binary_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30667bf8d368a37fa37f4165d90ee84362e360d83d85924898c41cfe3d097521"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hematite-nbt"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670d0784ee67cfb57393dc1837867d2951f9a59ca7db99a653499c854f745739"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cesu8",
|
||||
"flate2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "residua-cesu8"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ca29b145d9861719b5505602d881afc46705200144153ca9dbc0802be2938ea"
|
||||
|
||||
[[package]]
|
||||
name = "residua-mutf8"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2adba843a48e520e7dad6d1e9c367a4f818787eaccf4530c6b90dd1f035e630d"
|
||||
dependencies = [
|
||||
"residua-cesu8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_bytes"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdnbt"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"azalea-nbt",
|
||||
"byteorder",
|
||||
"criterion",
|
||||
"fastnbt",
|
||||
"flate2",
|
||||
"graphite_binary",
|
||||
"hematite-nbt",
|
||||
"residua-mutf8",
|
||||
"thiserror",
|
||||
"valence_nbt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
|
||||
|
||||
[[package]]
|
||||
name = "valence_nbt"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30d8921a6ebbb93ddbcd0e152611bd94fb928199efe8528077ab36787b298be4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cesu8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.37",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
52
simdnbt/Cargo.toml
Normal file
52
simdnbt/Cargo.toml
Normal file
|
@ -0,0 +1,52 @@
|
|||
[package]
|
||||
name = "simdnbt"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
description = "an unnecessarily fast nbt decoder"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/mat-1/simdnbt"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.4.3"
|
||||
flate2 = "^1.0.27"
|
||||
residua-mutf8 = "2.0.0"
|
||||
simdnbt-derive = { version = "0.1.0", path = "../simdnbt-derive", optional = true }
|
||||
thiserror = "1.0.47"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "^0.5.1", features = ["html_reports"] }
|
||||
graphite_binary = "0.1.0"
|
||||
valence_nbt = { version = "0.8.0", features = ["binary"] }
|
||||
fastnbt = "2.4.4"
|
||||
azalea-nbt = { git = "https://github.com/mat-1/azalea" }
|
||||
hematite-nbt = { version = "0.5.2", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["derive"]
|
||||
derive = ["dep:simdnbt-derive"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
debug = false
|
||||
|
||||
[profile.bench]
|
||||
lto = true
|
||||
debug = false
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "nbt"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "compare"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "compare_realworld"
|
||||
|
||||
[[bench]]
|
||||
harness = false
|
||||
name = "mutf8"
|
78
simdnbt/examples/hypixel.rs
Normal file
78
simdnbt/examples/hypixel.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use std::{collections::HashMap, hint::black_box, io::Cursor};
|
||||
|
||||
use simdnbt::{owned::Nbt, Deserialize};
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Item {
|
||||
pub id: i16,
|
||||
#[simdnbt(rename = "Damage")]
|
||||
pub damage: i16,
|
||||
#[simdnbt(rename = "Count")]
|
||||
pub count: i8,
|
||||
|
||||
pub tag: ItemTag,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ItemTag {
|
||||
#[simdnbt(rename = "SkullOwner")]
|
||||
pub skull_owner: Option<SkullOwner>,
|
||||
#[simdnbt(rename = "ExtraAttributes")]
|
||||
pub extra_attributes: ExtraAttributes,
|
||||
pub display: ItemDisplay,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ExtraAttributes {
|
||||
pub id: Option<String>,
|
||||
pub modifier: Option<String>,
|
||||
|
||||
pub ench: Option<simdnbt::owned::NbtCompound>,
|
||||
pub enchantments: Option<HashMap<String, i32>>,
|
||||
pub timestamp: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct SkullOwner {
|
||||
pub properties: Properties,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Properties {
|
||||
pub textures: Vec<Texture>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Texture {
|
||||
#[simdnbt(rename = "Value")]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct ItemDisplay {
|
||||
#[simdnbt(rename = "Name")]
|
||||
pub name: String,
|
||||
#[simdnbt(rename = "Lore")]
|
||||
pub lore: Vec<String>,
|
||||
|
||||
pub color: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Base {
|
||||
#[simdnbt(rename = "i")]
|
||||
pub items: Vec<Option<Item>>,
|
||||
}
|
||||
|
||||
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 = black_box(nbt.unwrap().unwrap());
|
||||
|
||||
let data = Base::from_nbt(nbt).unwrap().items;
|
||||
|
||||
println!("data: {data:?}");
|
||||
}
|
||||
}
|
|
@ -102,9 +102,10 @@ fn simdnbt_items_from_nbt(nbt: BaseNbt) -> Option<Vec<Option<Item>>> {
|
|||
fn main() {
|
||||
let input = black_box(include_bytes!("../tests/realworld.nbt"));
|
||||
|
||||
for _ in 0..10000 {
|
||||
for _ in 0..1 {
|
||||
let nbt = Nbt::read(&mut Cursor::new(input));
|
||||
let nbt = black_box(nbt.unwrap().unwrap());
|
||||
black_box(simdnbt_items_from_nbt(nbt));
|
||||
println!("{:?}", simdnbt_items_from_nbt(nbt));
|
||||
// black_box(simdnbt_items_from_nbt(nbt));
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
use super::{list::ListTag, NbtTag};
|
||||
use super::{list::NbtList, NbtTag};
|
||||
|
||||
/// A list of named tags. The order of the tags is preserved.
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
|
@ -66,7 +66,7 @@ impl<'a> NbtCompound<'a> {
|
|||
values.push((tag_name, NbtTag::ByteArray(read_with_u32_length(data, 1)?)))
|
||||
}
|
||||
STRING_ID => values.push((tag_name, NbtTag::String(read_string(data)?))),
|
||||
LIST_ID => values.push((tag_name, NbtTag::List(ListTag::read(data, depth + 1)?))),
|
||||
LIST_ID => values.push((tag_name, NbtTag::List(NbtList::read(data, depth + 1)?))),
|
||||
COMPOUND_ID => values.push((
|
||||
tag_name,
|
||||
NbtTag::Compound(NbtCompound::read_with_depth(data, depth + 1)?),
|
||||
|
@ -188,7 +188,7 @@ impl<'a> NbtCompound<'a> {
|
|||
pub fn string(&self, name: &str) -> Option<&Mutf8Str> {
|
||||
self.get(name).and_then(|tag| tag.string())
|
||||
}
|
||||
pub fn list(&self, name: &str) -> Option<&ListTag<'a>> {
|
||||
pub fn list(&self, name: &str) -> Option<&NbtList<'a>> {
|
||||
self.get(name).and_then(|tag| tag.list())
|
||||
}
|
||||
pub fn compound(&self, name: &str) -> Option<&NbtCompound<'a>> {
|
|
@ -18,7 +18,7 @@ use super::{read_u32, NbtCompound, MAX_DEPTH};
|
|||
/// A list of NBT tags of a single type.
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub enum ListTag<'a> {
|
||||
pub enum NbtList<'a> {
|
||||
#[default]
|
||||
Empty = END_ID,
|
||||
Byte(&'a [i8]) = BYTE_ID,
|
||||
|
@ -29,12 +29,12 @@ pub enum ListTag<'a> {
|
|||
Double(RawList<'a, f64>) = DOUBLE_ID,
|
||||
ByteArray(Vec<&'a [u8]>) = BYTE_ARRAY_ID,
|
||||
String(Vec<&'a Mutf8Str>) = STRING_ID,
|
||||
List(Vec<ListTag<'a>>) = LIST_ID,
|
||||
List(Vec<NbtList<'a>>) = LIST_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> {
|
||||
impl<'a> NbtList<'a> {
|
||||
pub fn read(data: &mut Cursor<&'a [u8]>, depth: usize) -> Result<Self, Error> {
|
||||
if depth > MAX_DEPTH {
|
||||
return Err(Error::MaxDepthExceeded);
|
||||
|
@ -43,15 +43,15 @@ impl<'a> ListTag<'a> {
|
|||
Ok(match tag_type {
|
||||
END_ID => {
|
||||
data.set_position(data.position() + 4);
|
||||
ListTag::Empty
|
||||
NbtList::Empty
|
||||
}
|
||||
BYTE_ID => ListTag::Byte(read_i8_array(data)?),
|
||||
SHORT_ID => ListTag::Short(RawList::new(read_with_u32_length(data, 2)?)),
|
||||
INT_ID => ListTag::Int(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
LONG_ID => ListTag::Long(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => ListTag::Float(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => ListTag::Double(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray({
|
||||
BYTE_ID => NbtList::Byte(read_i8_array(data)?),
|
||||
SHORT_ID => NbtList::Short(RawList::new(read_with_u32_length(data, 2)?)),
|
||||
INT_ID => NbtList::Int(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
LONG_ID => NbtList::Long(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => NbtList::Float(RawList::new(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => NbtList::Double(RawList::new(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => NbtList::ByteArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -60,7 +60,7 @@ impl<'a> ListTag<'a> {
|
|||
}
|
||||
arrays
|
||||
}),
|
||||
STRING_ID => ListTag::String({
|
||||
STRING_ID => NbtList::String({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut strings = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -69,16 +69,16 @@ impl<'a> ListTag<'a> {
|
|||
}
|
||||
strings
|
||||
}),
|
||||
LIST_ID => ListTag::List({
|
||||
LIST_ID => NbtList::List({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut lists = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
lists.push(ListTag::read(data, depth + 1)?)
|
||||
lists.push(NbtList::read(data, depth + 1)?)
|
||||
}
|
||||
lists
|
||||
}),
|
||||
COMPOUND_ID => ListTag::Compound({
|
||||
COMPOUND_ID => NbtList::Compound({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut compounds = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -87,7 +87,7 @@ impl<'a> ListTag<'a> {
|
|||
}
|
||||
compounds
|
||||
}),
|
||||
INT_ARRAY_ID => ListTag::IntArray({
|
||||
INT_ARRAY_ID => NbtList::IntArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -96,7 +96,7 @@ impl<'a> ListTag<'a> {
|
|||
}
|
||||
arrays
|
||||
}),
|
||||
LONG_ARRAY_ID => ListTag::LongArray({
|
||||
LONG_ARRAY_ID => NbtList::LongArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -111,7 +111,7 @@ impl<'a> ListTag<'a> {
|
|||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
// fast path for compound since it's very common to have lists of compounds
|
||||
if let ListTag::Compound(compounds) = self {
|
||||
if let NbtList::Compound(compounds) = self {
|
||||
data.reserve(5);
|
||||
// SAFETY: we just reserved 5 bytes
|
||||
unsafe {
|
||||
|
@ -126,55 +126,55 @@ impl<'a> ListTag<'a> {
|
|||
|
||||
data.push(self.id());
|
||||
match self {
|
||||
ListTag::Empty => {
|
||||
NbtList::Empty => {
|
||||
data.extend(&0u32.to_be_bytes());
|
||||
}
|
||||
ListTag::Byte(bytes) => {
|
||||
NbtList::Byte(bytes) => {
|
||||
write_with_u32_length(data, 1, slice_i8_into_u8(bytes));
|
||||
}
|
||||
ListTag::Short(shorts) => {
|
||||
NbtList::Short(shorts) => {
|
||||
write_with_u32_length(data, 2, shorts.as_big_endian());
|
||||
}
|
||||
ListTag::Int(ints) => {
|
||||
NbtList::Int(ints) => {
|
||||
write_with_u32_length(data, 4, ints.as_big_endian());
|
||||
}
|
||||
ListTag::Long(longs) => {
|
||||
NbtList::Long(longs) => {
|
||||
write_with_u32_length(data, 8, longs.as_big_endian());
|
||||
}
|
||||
ListTag::Float(floats) => {
|
||||
NbtList::Float(floats) => {
|
||||
write_with_u32_length(data, 4, floats.as_big_endian());
|
||||
}
|
||||
ListTag::Double(doubles) => {
|
||||
NbtList::Double(doubles) => {
|
||||
write_with_u32_length(data, 8, doubles.as_big_endian());
|
||||
}
|
||||
ListTag::ByteArray(byte_arrays) => {
|
||||
NbtList::ByteArray(byte_arrays) => {
|
||||
write_u32(data, byte_arrays.len() as u32);
|
||||
for array in byte_arrays.iter() {
|
||||
write_with_u32_length(data, 1, array);
|
||||
}
|
||||
}
|
||||
ListTag::String(strings) => {
|
||||
NbtList::String(strings) => {
|
||||
write_u32(data, strings.len() as u32);
|
||||
for string in strings {
|
||||
write_string(data, string);
|
||||
}
|
||||
}
|
||||
ListTag::List(lists) => {
|
||||
NbtList::List(lists) => {
|
||||
write_u32(data, lists.len() as u32);
|
||||
for list in lists {
|
||||
list.write(data);
|
||||
}
|
||||
}
|
||||
ListTag::Compound(_) => {
|
||||
NbtList::Compound(_) => {
|
||||
unreachable!("fast path for compound should have been taken")
|
||||
}
|
||||
ListTag::IntArray(int_arrays) => {
|
||||
NbtList::IntArray(int_arrays) => {
|
||||
write_u32(data, int_arrays.len() as u32);
|
||||
for array in int_arrays {
|
||||
write_with_u32_length(data, 4, array.as_big_endian());
|
||||
}
|
||||
}
|
||||
ListTag::LongArray(long_arrays) => {
|
||||
NbtList::LongArray(long_arrays) => {
|
||||
write_u32(data, long_arrays.len() as u32);
|
||||
for array in long_arrays {
|
||||
write_with_u32_length(data, 8, array.as_big_endian());
|
||||
|
@ -195,73 +195,73 @@ impl<'a> ListTag<'a> {
|
|||
|
||||
pub fn bytes(&self) -> Option<&[i8]> {
|
||||
match self {
|
||||
ListTag::Byte(bytes) => Some(bytes),
|
||||
NbtList::Byte(bytes) => Some(bytes),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn shorts(&self) -> Option<Vec<i16>> {
|
||||
match self {
|
||||
ListTag::Short(shorts) => Some(shorts.to_vec()),
|
||||
NbtList::Short(shorts) => Some(shorts.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn ints(&self) -> Option<Vec<i32>> {
|
||||
match self {
|
||||
ListTag::Int(ints) => Some(ints.to_vec()),
|
||||
NbtList::Int(ints) => Some(ints.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn longs(&self) -> Option<Vec<i64>> {
|
||||
match self {
|
||||
ListTag::Long(longs) => Some(longs.to_vec()),
|
||||
NbtList::Long(longs) => Some(longs.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn floats(&self) -> Option<Vec<f32>> {
|
||||
match self {
|
||||
ListTag::Float(floats) => Some(floats.to_vec()),
|
||||
NbtList::Float(floats) => Some(floats.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn doubles(&self) -> Option<Vec<f64>> {
|
||||
match self {
|
||||
ListTag::Double(doubles) => Some(doubles.to_vec()),
|
||||
NbtList::Double(doubles) => Some(doubles.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn byte_arrays(&self) -> Option<&Vec<&[u8]>> {
|
||||
match self {
|
||||
ListTag::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
NbtList::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn strings(&self) -> Option<&[&Mutf8Str]> {
|
||||
match self {
|
||||
ListTag::String(strings) => Some(strings),
|
||||
NbtList::String(strings) => Some(strings),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn lists(&self) -> Option<&[ListTag]> {
|
||||
pub fn lists(&self) -> Option<&[NbtList]> {
|
||||
match self {
|
||||
ListTag::List(lists) => Some(lists),
|
||||
NbtList::List(lists) => Some(lists),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn compounds(&self) -> Option<&[NbtCompound]> {
|
||||
match self {
|
||||
ListTag::Compound(compounds) => Some(compounds),
|
||||
NbtList::Compound(compounds) => Some(compounds),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn int_arrays(&self) -> Option<&[RawList<i32>]> {
|
||||
match self {
|
||||
ListTag::IntArray(int_arrays) => Some(int_arrays),
|
||||
NbtList::IntArray(int_arrays) => Some(int_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn long_arrays(&self) -> Option<&[RawList<i64>]> {
|
||||
match self {
|
||||
ListTag::LongArray(long_arrays) => Some(long_arrays),
|
||||
NbtList::LongArray(long_arrays) => Some(long_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
pub use self::{compound::NbtCompound, list::ListTag};
|
||||
pub use self::{compound::NbtCompound, list::NbtList};
|
||||
|
||||
/// A complete NBT container. This contains a name and a compound tag.
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -111,7 +111,7 @@ pub enum NbtTag<'a> {
|
|||
Double(f64) = DOUBLE_ID,
|
||||
ByteArray(&'a [u8]) = BYTE_ARRAY_ID,
|
||||
String(&'a Mutf8Str) = STRING_ID,
|
||||
List(ListTag<'a>) = LIST_ID,
|
||||
List(NbtList<'a>) = LIST_ID,
|
||||
Compound(NbtCompound<'a>) = COMPOUND_ID,
|
||||
IntArray(RawList<'a, i32>) = INT_ARRAY_ID,
|
||||
LongArray(RawList<'a, i64>) = LONG_ARRAY_ID,
|
||||
|
@ -175,7 +175,7 @@ impl<'a> NbtTag<'a> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn list(&self) -> Option<&ListTag<'a>> {
|
||||
pub fn list(&self) -> Option<&NbtList<'a>> {
|
||||
match self {
|
||||
NbtTag::List(list) => Some(list),
|
||||
_ => None,
|
|
@ -13,3 +13,11 @@ pub enum Error {
|
|||
#[error("Tried to read NBT tag with too high complexity, depth > {MAX_DEPTH}")]
|
||||
MaxDepthExceeded,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DeserializeError {
|
||||
#[error("Missing field")]
|
||||
MissingField,
|
||||
#[error("Mismatched type")]
|
||||
MismatchedFieldType,
|
||||
}
|
|
@ -22,6 +22,10 @@ mod mutf8;
|
|||
pub mod owned;
|
||||
pub mod raw_list;
|
||||
pub mod swap_endianness;
|
||||
mod traits;
|
||||
|
||||
pub use error::Error;
|
||||
pub use error::{DeserializeError, Error};
|
||||
pub use mutf8::Mutf8Str;
|
||||
pub use traits::{Deserialize, FromNbtTag};
|
||||
|
||||
pub use simdnbt_derive::*;
|
|
@ -1,4 +1,4 @@
|
|||
use std::io::Cursor;
|
||||
use std::{io::Cursor, mem};
|
||||
|
||||
use byteorder::{ReadBytesExt, BE};
|
||||
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
use super::{list::ListTag, NbtTag};
|
||||
use super::{list::NbtList, NbtTag};
|
||||
|
||||
/// A list of named tags. The order of the tags is preserved.
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
|
@ -72,7 +72,7 @@ impl NbtCompound {
|
|||
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)?))),
|
||||
LIST_ID => values.push((tag_name, NbtTag::List(NbtList::read(data, depth + 1)?))),
|
||||
COMPOUND_ID => values.push((
|
||||
tag_name,
|
||||
NbtTag::Compound(NbtCompound::read_with_depth(data, depth + 1)?),
|
||||
|
@ -174,6 +174,20 @@ impl NbtCompound {
|
|||
None
|
||||
}
|
||||
|
||||
/// Get an owned tag from the compound by swapping it with a dummy tag.
|
||||
pub fn take(&mut self, name: &str) -> Option<NbtTag> {
|
||||
let name = Mutf8Str::from_str(name);
|
||||
let name = name.as_ref();
|
||||
for i in 0..self.values.len() {
|
||||
if self.values[i].0.as_str() == name {
|
||||
let mut value = NbtTag::Byte(0);
|
||||
mem::swap(&mut self.values[i].1, &mut value);
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns whether there is a tag with the given name.
|
||||
pub fn contains(&self, name: &str) -> bool {
|
||||
let name = Mutf8Str::from_str(name);
|
||||
|
@ -234,10 +248,10 @@ impl NbtCompound {
|
|||
pub fn string_mut(&mut self, name: &str) -> Option<&mut Mutf8String> {
|
||||
self.get_mut(name).and_then(|tag| tag.string_mut())
|
||||
}
|
||||
pub fn list(&self, name: &str) -> Option<&ListTag> {
|
||||
pub fn list(&self, name: &str) -> Option<&NbtList> {
|
||||
self.get(name).and_then(|tag| tag.list())
|
||||
}
|
||||
pub fn list_mut(&mut self, name: &str) -> Option<&mut ListTag> {
|
||||
pub fn list_mut(&mut self, name: &str) -> Option<&mut NbtList> {
|
||||
self.get_mut(name).and_then(|tag| tag.list_mut())
|
||||
}
|
||||
pub fn compound(&self, name: &str) -> Option<&NbtCompound> {
|
|
@ -20,7 +20,7 @@ use super::{compound::NbtCompound, read_u32, MAX_DEPTH};
|
|||
/// A list of NBT tags of a single type.
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub enum ListTag {
|
||||
pub enum NbtList {
|
||||
#[default]
|
||||
Empty = END_ID,
|
||||
Byte(Vec<i8>) = BYTE_ID,
|
||||
|
@ -31,12 +31,12 @@ pub enum ListTag {
|
|||
Double(Vec<f64>) = DOUBLE_ID,
|
||||
ByteArray(Vec<Vec<u8>>) = BYTE_ARRAY_ID,
|
||||
String(Vec<Mutf8String>) = STRING_ID,
|
||||
List(Vec<ListTag>) = LIST_ID,
|
||||
List(Vec<NbtList>) = LIST_ID,
|
||||
Compound(Vec<NbtCompound>) = COMPOUND_ID,
|
||||
IntArray(Vec<Vec<i32>>) = INT_ARRAY_ID,
|
||||
LongArray(Vec<Vec<i64>>) = LONG_ARRAY_ID,
|
||||
}
|
||||
impl ListTag {
|
||||
impl NbtList {
|
||||
pub fn read(data: &mut Cursor<&[u8]>, depth: usize) -> Result<Self, Error> {
|
||||
if depth > MAX_DEPTH {
|
||||
return Err(Error::MaxDepthExceeded);
|
||||
|
@ -45,15 +45,15 @@ impl ListTag {
|
|||
Ok(match tag_type {
|
||||
END_ID => {
|
||||
data.set_position(data.position() + 4);
|
||||
ListTag::Empty
|
||||
NbtList::Empty
|
||||
}
|
||||
BYTE_ID => ListTag::Byte(read_i8_array(data)?.to_owned()),
|
||||
SHORT_ID => ListTag::Short(swap_endianness(read_with_u32_length(data, 2)?)),
|
||||
INT_ID => ListTag::Int(swap_endianness(read_with_u32_length(data, 4)?)),
|
||||
LONG_ID => ListTag::Long(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => ListTag::Float(swap_endianness(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => ListTag::Double(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => ListTag::ByteArray({
|
||||
BYTE_ID => NbtList::Byte(read_i8_array(data)?.to_owned()),
|
||||
SHORT_ID => NbtList::Short(swap_endianness(read_with_u32_length(data, 2)?)),
|
||||
INT_ID => NbtList::Int(swap_endianness(read_with_u32_length(data, 4)?)),
|
||||
LONG_ID => NbtList::Long(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
FLOAT_ID => NbtList::Float(swap_endianness(read_with_u32_length(data, 4)?)),
|
||||
DOUBLE_ID => NbtList::Double(swap_endianness(read_with_u32_length(data, 8)?)),
|
||||
BYTE_ARRAY_ID => NbtList::ByteArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -62,7 +62,7 @@ impl ListTag {
|
|||
}
|
||||
arrays
|
||||
}),
|
||||
STRING_ID => ListTag::String({
|
||||
STRING_ID => NbtList::String({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut strings = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -71,16 +71,16 @@ impl ListTag {
|
|||
}
|
||||
strings
|
||||
}),
|
||||
LIST_ID => ListTag::List({
|
||||
LIST_ID => NbtList::List({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut lists = Vec::with_capacity(length.min(128) as usize);
|
||||
for _ in 0..length {
|
||||
lists.push(ListTag::read(data, depth + 1)?)
|
||||
lists.push(NbtList::read(data, depth + 1)?)
|
||||
}
|
||||
lists
|
||||
}),
|
||||
COMPOUND_ID => ListTag::Compound({
|
||||
COMPOUND_ID => NbtList::Compound({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut compounds = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -89,7 +89,7 @@ impl ListTag {
|
|||
}
|
||||
compounds
|
||||
}),
|
||||
INT_ARRAY_ID => ListTag::IntArray({
|
||||
INT_ARRAY_ID => NbtList::IntArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -98,7 +98,7 @@ impl ListTag {
|
|||
}
|
||||
arrays
|
||||
}),
|
||||
LONG_ARRAY_ID => ListTag::LongArray({
|
||||
LONG_ARRAY_ID => NbtList::LongArray({
|
||||
let length = read_u32(data)?;
|
||||
// arbitrary number to prevent big allocations
|
||||
let mut arrays = Vec::with_capacity(length.min(128) as usize);
|
||||
|
@ -113,7 +113,7 @@ impl ListTag {
|
|||
|
||||
pub fn write(&self, data: &mut Vec<u8>) {
|
||||
// fast path for compound since it's very common to have lists of compounds
|
||||
if let ListTag::Compound(compounds) = self {
|
||||
if let NbtList::Compound(compounds) = self {
|
||||
data.reserve(5);
|
||||
// SAFETY: we just reserved 5 bytes
|
||||
unsafe {
|
||||
|
@ -128,55 +128,55 @@ impl ListTag {
|
|||
|
||||
data.push(self.id());
|
||||
match self {
|
||||
ListTag::Empty => {
|
||||
NbtList::Empty => {
|
||||
data.extend(&0u32.to_be_bytes());
|
||||
}
|
||||
ListTag::Byte(bytes) => {
|
||||
NbtList::Byte(bytes) => {
|
||||
write_with_u32_length(data, 1, slice_i8_into_u8(bytes));
|
||||
}
|
||||
ListTag::Short(shorts) => {
|
||||
NbtList::Short(shorts) => {
|
||||
write_with_u32_length(data, 2, &slice_into_u8_big_endian(shorts));
|
||||
}
|
||||
ListTag::Int(ints) => {
|
||||
NbtList::Int(ints) => {
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(ints));
|
||||
}
|
||||
ListTag::Long(longs) => {
|
||||
NbtList::Long(longs) => {
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(longs));
|
||||
}
|
||||
ListTag::Float(floats) => {
|
||||
NbtList::Float(floats) => {
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(floats));
|
||||
}
|
||||
ListTag::Double(doubles) => {
|
||||
NbtList::Double(doubles) => {
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(doubles));
|
||||
}
|
||||
ListTag::ByteArray(byte_arrays) => {
|
||||
NbtList::ByteArray(byte_arrays) => {
|
||||
write_u32(data, byte_arrays.len() as u32);
|
||||
for array in byte_arrays {
|
||||
write_with_u32_length(data, 1, array);
|
||||
}
|
||||
}
|
||||
ListTag::String(strings) => {
|
||||
NbtList::String(strings) => {
|
||||
write_u32(data, strings.len() as u32);
|
||||
for string in strings {
|
||||
write_string(data, string);
|
||||
}
|
||||
}
|
||||
ListTag::List(lists) => {
|
||||
NbtList::List(lists) => {
|
||||
write_u32(data, lists.len() as u32);
|
||||
for list in lists {
|
||||
list.write(data);
|
||||
}
|
||||
}
|
||||
ListTag::Compound(_) => {
|
||||
NbtList::Compound(_) => {
|
||||
unreachable!("fast path for compound should have been taken")
|
||||
}
|
||||
ListTag::IntArray(int_arrays) => {
|
||||
NbtList::IntArray(int_arrays) => {
|
||||
write_u32(data, int_arrays.len() as u32);
|
||||
for array in int_arrays {
|
||||
write_with_u32_length(data, 4, &slice_into_u8_big_endian(array));
|
||||
}
|
||||
}
|
||||
ListTag::LongArray(long_arrays) => {
|
||||
NbtList::LongArray(long_arrays) => {
|
||||
write_u32(data, long_arrays.len() as u32);
|
||||
for array in long_arrays {
|
||||
write_with_u32_length(data, 8, &slice_into_u8_big_endian(array));
|
||||
|
@ -197,73 +197,156 @@ impl ListTag {
|
|||
|
||||
pub fn bytes(&self) -> Option<&[i8]> {
|
||||
match self {
|
||||
ListTag::Byte(bytes) => Some(bytes),
|
||||
NbtList::Byte(bytes) => Some(bytes),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_bytes(self) -> Option<Vec<i8>> {
|
||||
match self {
|
||||
NbtList::Byte(bytes) => Some(bytes),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shorts(&self) -> Option<Vec<i16>> {
|
||||
match self {
|
||||
ListTag::Short(shorts) => Some(shorts.to_vec()),
|
||||
NbtList::Short(shorts) => Some(shorts.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_shorts(self) -> Option<Vec<i16>> {
|
||||
match self {
|
||||
NbtList::Short(shorts) => Some(shorts),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ints(&self) -> Option<Vec<i32>> {
|
||||
match self {
|
||||
ListTag::Int(ints) => Some(ints.to_vec()),
|
||||
NbtList::Int(ints) => Some(ints.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_ints(self) -> Option<Vec<i32>> {
|
||||
match self {
|
||||
NbtList::Int(ints) => Some(ints),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn longs(&self) -> Option<Vec<i64>> {
|
||||
match self {
|
||||
ListTag::Long(longs) => Some(longs.to_vec()),
|
||||
NbtList::Long(longs) => Some(longs.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_longs(self) -> Option<Vec<i64>> {
|
||||
match self {
|
||||
NbtList::Long(longs) => Some(longs),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn floats(&self) -> Option<Vec<f32>> {
|
||||
match self {
|
||||
ListTag::Float(floats) => Some(floats.to_vec()),
|
||||
NbtList::Float(floats) => Some(floats.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_floats(self) -> Option<Vec<f32>> {
|
||||
match self {
|
||||
NbtList::Float(floats) => Some(floats),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn doubles(&self) -> Option<Vec<f64>> {
|
||||
match self {
|
||||
ListTag::Double(doubles) => Some(doubles.to_vec()),
|
||||
NbtList::Double(doubles) => Some(doubles.to_vec()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_doubles(self) -> Option<Vec<f64>> {
|
||||
match self {
|
||||
NbtList::Double(doubles) => Some(doubles),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn byte_arrays(&self) -> Option<&[Vec<u8>]> {
|
||||
match self {
|
||||
ListTag::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
NbtList::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_byte_arrays(self) -> Option<Vec<Vec<u8>>> {
|
||||
match self {
|
||||
NbtList::ByteArray(byte_arrays) => Some(byte_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn strings(&self) -> Option<&[Mutf8String]> {
|
||||
match self {
|
||||
ListTag::String(strings) => Some(strings),
|
||||
NbtList::String(strings) => Some(strings),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn lists(&self) -> Option<&[ListTag]> {
|
||||
pub fn into_strings(self) -> Option<Vec<Mutf8String>> {
|
||||
match self {
|
||||
ListTag::List(lists) => Some(lists),
|
||||
NbtList::String(strings) => Some(strings),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lists(&self) -> Option<&[NbtList]> {
|
||||
match self {
|
||||
NbtList::List(lists) => Some(lists),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_lists(self) -> Option<Vec<NbtList>> {
|
||||
match self {
|
||||
NbtList::List(lists) => Some(lists),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compounds(&self) -> Option<&[NbtCompound]> {
|
||||
match self {
|
||||
ListTag::Compound(compounds) => Some(compounds),
|
||||
NbtList::Compound(compounds) => Some(compounds),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_compounds(self) -> Option<Vec<NbtCompound>> {
|
||||
match self {
|
||||
NbtList::Compound(compounds) => Some(compounds),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn int_arrays(&self) -> Option<&[Vec<i32>]> {
|
||||
match self {
|
||||
ListTag::IntArray(int_arrays) => Some(int_arrays),
|
||||
NbtList::IntArray(int_arrays) => Some(int_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_int_arrays(self) -> Option<Vec<Vec<i32>>> {
|
||||
match self {
|
||||
NbtList::IntArray(int_arrays) => Some(int_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn long_arrays(&self) -> Option<&[Vec<i64>]> {
|
||||
match self {
|
||||
ListTag::LongArray(long_arrays) => Some(long_arrays),
|
||||
NbtList::LongArray(long_arrays) => Some(long_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_long_arrays(self) -> Option<Vec<Vec<i64>>> {
|
||||
match self {
|
||||
NbtList::LongArray(long_arrays) => Some(long_arrays),
|
||||
_ => None,
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
Error, Mutf8Str,
|
||||
};
|
||||
|
||||
pub use self::{compound::NbtCompound, list::ListTag};
|
||||
pub use self::{compound::NbtCompound, list::NbtList};
|
||||
|
||||
/// A complete NBT container. This contains a name and a compound tag.
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
|
@ -134,6 +134,10 @@ impl BaseNbt {
|
|||
pub fn into_iter(self) -> impl Iterator<Item = (Mutf8String, NbtTag)> {
|
||||
self.tag.into_iter()
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> NbtCompound {
|
||||
self.tag
|
||||
}
|
||||
}
|
||||
impl Deref for BaseNbt {
|
||||
type Target = NbtCompound;
|
||||
|
@ -155,7 +159,7 @@ pub enum NbtTag {
|
|||
Double(f64) = DOUBLE_ID,
|
||||
ByteArray(Vec<u8>) = BYTE_ARRAY_ID,
|
||||
String(Mutf8String) = STRING_ID,
|
||||
List(ListTag) = LIST_ID,
|
||||
List(NbtList) = LIST_ID,
|
||||
Compound(NbtCompound) = COMPOUND_ID,
|
||||
IntArray(Vec<i32>) = INT_ARRAY_ID,
|
||||
LongArray(Vec<i64>) = LONG_ARRAY_ID,
|
||||
|
@ -323,19 +327,19 @@ impl NbtTag {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn list(&self) -> Option<&ListTag> {
|
||||
pub fn list(&self) -> Option<&NbtList> {
|
||||
match self {
|
||||
NbtTag::List(list) => Some(list),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn list_mut(&mut self) -> Option<&mut ListTag> {
|
||||
pub fn list_mut(&mut self) -> Option<&mut NbtList> {
|
||||
match self {
|
||||
NbtTag::List(list) => Some(list),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn into_list(self) -> Option<ListTag> {
|
||||
pub fn into_list(self) -> Option<NbtList> {
|
||||
match self {
|
||||
NbtTag::List(list) => Some(list),
|
||||
_ => None,
|
148
simdnbt/src/traits.rs
Normal file
148
simdnbt/src/traits.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::DeserializeError;
|
||||
|
||||
pub trait Deserialize: Sized {
|
||||
fn from_nbt(nbt: crate::owned::BaseNbt) -> Result<Self, DeserializeError> {
|
||||
Self::from_compound(nbt.into_inner())
|
||||
}
|
||||
|
||||
fn from_compound(compound: crate::owned::NbtCompound) -> Result<Self, DeserializeError>;
|
||||
}
|
||||
|
||||
impl<T: FromNbtTag> Deserialize for HashMap<String, T> {
|
||||
fn from_compound(compound: crate::owned::NbtCompound) -> Result<Self, DeserializeError> {
|
||||
let mut hashmap = HashMap::with_capacity(compound.values.len());
|
||||
|
||||
for (k, v) in compound.values {
|
||||
hashmap.insert(
|
||||
k.to_string(),
|
||||
T::from_nbt_tag(v).ok_or(DeserializeError::MismatchedFieldType)?,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(hashmap)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for crate::owned::NbtCompound {
|
||||
fn from_compound(compound: crate::owned::NbtCompound) -> Result<Self, DeserializeError> {
|
||||
Ok(compound)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FromNbtTag: Sized {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self>;
|
||||
fn from_optional_nbt_tag(
|
||||
tag: Option<crate::owned::NbtTag>,
|
||||
) -> Result<Option<Self>, DeserializeError> {
|
||||
match tag {
|
||||
Some(tag) => Ok(Self::from_nbt_tag(tag)),
|
||||
None => Err(DeserializeError::MissingField),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Deserialize> FromNbtTag for T {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.into_compound()
|
||||
.and_then(|c| Self::from_compound(c).ok())
|
||||
}
|
||||
}
|
||||
|
||||
// standard nbt types
|
||||
impl FromNbtTag for i8 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.byte()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for i16 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.short()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for i32 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.int()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for i64 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.long()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for f32 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.float()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for f64 {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.double()
|
||||
}
|
||||
}
|
||||
impl FromNbtTag for String {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.string().map(|s| s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// lists
|
||||
impl FromNbtTag for Vec<String> {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.list().and_then(|l| {
|
||||
l.strings()
|
||||
.map(|s| s.iter().map(|s| s.to_string()).collect())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// slightly less standard types
|
||||
impl<T: FromNbtTag> FromNbtTag for Option<T> {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
Some(T::from_nbt_tag(tag))
|
||||
}
|
||||
fn from_optional_nbt_tag(
|
||||
tag: Option<crate::owned::NbtTag>,
|
||||
) -> Result<Option<Self>, DeserializeError> {
|
||||
match tag {
|
||||
Some(tag) => Ok(Some(T::from_nbt_tag(tag))),
|
||||
None => Ok(Some(None)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Deserialize> FromNbtTag for Vec<Option<T>> {
|
||||
/// A list of compounds where `None` is an empty compound
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
let list = tag.into_list()?.into_compounds()?;
|
||||
let mut vec = Vec::with_capacity(list.len());
|
||||
for tag in list {
|
||||
if tag.values.is_empty() {
|
||||
vec.push(None);
|
||||
} else {
|
||||
vec.push(Some(T::from_compound(tag).ok()?));
|
||||
}
|
||||
}
|
||||
|
||||
Some(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Deserialize> FromNbtTag for Vec<T> {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
let list = tag.into_list()?.into_compounds()?;
|
||||
let mut vec = Vec::with_capacity(list.len());
|
||||
for tag in list {
|
||||
vec.push(T::from_compound(tag).ok()?);
|
||||
}
|
||||
|
||||
Some(vec)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNbtTag for bool {
|
||||
fn from_nbt_tag(tag: crate::owned::NbtTag) -> Option<Self> {
|
||||
tag.byte().map(|b| b != 0)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue