1use std::io::Read;
2
3use base64::Engine;
4use flate2::read::GzDecoder;
5use serde_json::Value;
6
7#[derive(Debug, thiserror::Error)]
9#[non_exhaustive]
10pub enum NbtError {
11 #[error("invalid base64: {0}")]
13 Base64(#[from] base64::DecodeError),
14 #[error("gzip decompression failed: {0}")]
16 Gzip(#[source] std::io::Error),
17 #[error("invalid NBT: {0}")]
19 Nbt(#[from] fastnbt::error::Error),
20 #[error("no NBT data field present")]
22 MissingData,
23}
24
25pub fn decode_nbt(encoded: &str) -> Result<fastnbt::Value, NbtError> {
30 let compressed = base64::engine::general_purpose::STANDARD.decode(encoded.trim())?;
31 let mut decoder = GzDecoder::new(&compressed[..]);
32 let mut bytes = Vec::new();
33 decoder.read_to_end(&mut bytes).map_err(NbtError::Gzip)?;
34 Ok(fastnbt::from_bytes(&bytes)?)
35}
36
37pub fn decode_inventory(section: &Value) -> Result<fastnbt::Value, NbtError> {
41 let encoded = match section {
42 Value::String(s) => s.as_str(),
43 Value::Object(map) => map
44 .get("data")
45 .and_then(Value::as_str)
46 .ok_or(NbtError::MissingData)?,
47 _ => return Err(NbtError::MissingData),
48 };
49 decode_nbt(encoded)
50}