owengage / fastnbt

Fast serde serializer and deserializer for Minecraft's NBT and Anvil formats
MIT License
186 stars 34 forks source link

Unexpected Array Type when trying to deserialize Byte/Int/LongArray #50

Closed maddymakesgames closed 2 years ago

maddymakesgames commented 2 years ago

I'm trying to use fastnbt to deserialize bigtest.nbt and I'm getting "unexpected array type." The error goes away if I comment out the LongArray and ByteArray fields.

use std::io::Read;

use fastnbt::{de::from_bytes, ByteArray, IntArray, LongArray};
use flate2::read::GzDecoder;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct Big1Sub1 {
    name: String,
    #[serde(rename = "created-on")]
    created_on: i64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Big1Sub2 {
    name: String,
    value: f32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Big1Sub3 {
    ham: Big1Sub2,
    egg: Big1Sub2,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Big1 {
    #[serde(rename = "listTest (compound)")]
    list_test_compound: Vec<Big1Sub1>,
    #[serde(rename = "longTest")]
    long_test: i64,
    #[serde(rename = "shortTest")]
    short_test: i32,
    #[serde(rename = "byteTest")]
    byte_test: i8,
    #[serde(rename = "floatTest")]
    float_test: f64,
    #[serde(rename = "nested compound test")]
    nested_compound_test: Big1Sub3,
    #[serde(
        rename = "byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"
    )]
    byte_array_test: ByteArray,
    #[serde(rename = "stringTest")]
    string_test: String,
    #[serde(rename = "listTest (long)")]
    list_test_long: LongArray,
    #[serde(rename = "doubleTest")]
    double_test: f64,
    #[serde(rename = "intTest")]
    int_test: i32,
}

fn inflate(buf: &[u8]) -> Vec<u8> {
    let mut decoder = GzDecoder::new(buf);
    let mut dest = Vec::new();
    decoder.read_to_end(&mut dest).unwrap();
    dest
}

fn main() {
    let mut file = std::fs::File::open("./bigtest.nbt").unwrap();
    let mut bytes = Vec::new();
    file.read_to_end(&mut bytes).unwrap();
    let uncompressed = inflate(&bytes);

    let data: Big1 = from_bytes(&uncompressed).unwrap();
    println!("{:?}", data);
}
owengage commented 2 years ago

Hey! Thanks for the issue. I had a look at your bigtest.nbt, and it looks like your list_test_long field (renamed to listTest (long)) is actually a list of longs, rather than a LongArray. NBT has two ways of storing lists of byte/int/long and they're not interchangable.

If you want to capture a list of longs you can use Vec<i64> instead.

The error message produced here could definitely be improved, as could the documentation around it. That's something I'll keep in mind in future.

maddymakesgames commented 2 years ago

whoops, thanks, thought I had tried that but must have changed the ByteArray at the same time.