feat: add support for compressed NBT

this switches from hematite_nbt to fastnbt.
This commit is contained in:
LordMZTE 2022-05-06 16:46:45 +02:00
parent 0abae7876f
commit e30765f7c1
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
2 changed files with 48 additions and 5 deletions

View file

@ -12,7 +12,8 @@ serde = "1.0"
serde-value = "0.7"
ciborium = "0.2.0"
hematite-nbt = "0.5.2"
fastnbt = "2.1.0"
flate2 = "1.0.23"
ron = "0.7.0"
serde-lexpr = "0.1.2"
serde-xml-rs = "0.5.1"

View file

@ -1,5 +1,10 @@
use std::io::{Read, Write};
use flate2::{
bufread::{GzDecoder, ZlibDecoder},
write::GzEncoder,
Compression,
};
use miette::{Context, IntoDiagnostic};
use sercon_base::Backend;
use serde_value::Value;
@ -9,16 +14,53 @@ pub struct NbtBackend;
impl Backend for NbtBackend {
fn serialize(&self, out: &mut dyn Write, data: Value) -> miette::Result<()> {
nbt::to_writer(out, &data, None)
let gz = GzEncoder::new(out, Compression::new(5));
fastnbt::to_writer(gz, &data)
.into_diagnostic()
.wrap_err("NBT serialization error")
.wrap_err("failed to serialize NBT data")?;
Ok(())
}
fn deserialize(&self, data: &mut dyn Read) -> miette::Result<Value> {
nbt::from_reader(data)
let mut vec = vec![];
data.read_to_end(&mut vec).into_diagnostic()?;
let compression = vec
.get(0..2)
.map(|m| match m {
[0x1f, 0x8b] => CompressionType::Gzip,
[0x78, 0x01] | [0x78, 0x9C] | [0x78, 0xDA] => CompressionType::Zlib,
_ => CompressionType::None,
})
.unwrap_or(CompressionType::None);
let mut decomp = vec![];
match compression {
CompressionType::Gzip => {
GzDecoder::new(&vec[..])
.read_to_end(&mut decomp)
.into_diagnostic()
.wrap_err("data gz decompression failed")?;
},
CompressionType::Zlib => {
ZlibDecoder::new(&vec[..])
.read_to_end(&mut decomp)
.into_diagnostic()
.wrap_err("data zlib decompression failed")?;
},
CompressionType::None => decomp.copy_from_slice(&vec),
}
fastnbt::from_bytes(&decomp)
.into_diagnostic()
.wrap_err("NBT deserialization error")
.wrap_err("NBT deserialization failed")
}
}
impl_filetype_backend!(NbtBackend, ["nbt"]);
enum CompressionType {
Gzip,
Zlib,
None,
}