use crate::data::{NbtItem, NbtList, NbtValue, Reader}; use std::io::{BufRead, Cursor, Read}; /// 输出类型标识符 /// 类型标识符 /// (0x07) Vec /// (0x08) UTF-8 String (Arc) /// (0x09) Vec /// (0x0A) Compound /// (0x0B) Vec /// (0x0C) Vec pub mod read_data { use crate::data::{NbtItem, NbtLength, NbtList, NbtValue, Reader}; use std::collections::HashMap; use std::io::Read; use std::sync::Arc; /// 直接读取长度和值 不带名称 /// 反正名字都在外面读过 #[inline] pub fn from_i8_array(value: &mut Reader) -> Vec { // 读取长度 let mut buff = [0_u8; 4]; _ = value.read(&mut buff).unwrap(); let len = NbtLength::from_be_bytes(buff); let mut vec = Vec::with_capacity(len as usize); for _ in 0..len { vec.push(NbtValue::from_i8(value).as_i8().unwrap()); } vec } /// 直接读取长度和值 不带名称 #[inline] pub fn from_i32_array(value: &mut Reader) -> Vec { // 读取长度 let mut buff = [0_u8; 4]; _ = value.read(&mut buff).unwrap(); let len = NbtLength::from_be_bytes(buff); let mut vec = Vec::with_capacity(len as usize); for _ in 0..len { vec.push(NbtValue::from_i32(value).as_i32().unwrap()); } vec } /// 直接读取长度和值 不带名称 #[inline] pub fn from_i64_array(value: &mut Reader) -> Vec { // 读取长度 let mut buff = [0_u8; 4]; _ = value.read(&mut buff).unwrap(); let len = NbtLength::from_be_bytes(buff); let mut vec = Vec::with_capacity(len as usize); for _ in 0..len { vec.push(NbtValue::from_i64(value).as_i64().unwrap()); } vec } /// 直接读取长度和值 不带名称 /// 主要是为了可以直接递归 ( pub fn from_nbt_list(value: &mut Reader) -> Vec { // 读取长度 let mut buff = [0_u8; 4]; _ = value.read(&mut buff).unwrap(); let len = NbtLength::from_be_bytes(buff); let mut vec: Vec = Vec::with_capacity(len as usize); // 先读取 type let mut type_buff = [0_u8; 1]; _ = value.read(&mut type_buff).unwrap(); match type_buff { [0x00] => { // End todo!() } [0x01] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_i8(value))); } } [0x02] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_i16(value))); } } [0x03] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_i32(value))); } } [0x04] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_i64(value))); } } [0x05] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_f32(value))); } } [0x06] => { for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_f64(value))); } } [0x07] => { // ByteArray for _ in 0..len { vec.push(NbtItem::from(from_i8_array(value))); } } [0x08] => { // string for _ in 0..len { vec.push(NbtItem::Value(NbtValue::from_string(value))); } } [0x09] => { // NbtList // 要命 (虽说没 Compound 那么麻烦) // 直接递归就行 for _ in 0..len { vec.push(NbtItem::from(from_nbt_list(value))); } } [0x0A] => { // Compound // 他甚至不告诉你有多少个元素,要命 for _ in 0..len { vec.push(NbtItem::from(from_compound(value))); } } [0x0B] => { // IntArray for _ in 0..len { vec.push(NbtItem::from(from_i32_array(value))); } } [0x0C] => { // LongArray for _ in 0..len { vec.push(NbtItem::from(from_i64_array(value))); } } _ => { panic!( "{}", format!( "WTF while reading Nbt List \ntype: {:?}\nreader pos: {:?}", type_buff, value.position() ) ); } } vec } /// 直接读取长度和值 不带名称 /// 只不过 Compound 不带长度,得自己试 pub fn from_compound(value: &mut Reader) -> NbtList { // 进来直接是 values // loop 读取长度 name len name value value // 直到一个 End #[cfg(feature = "core_debug")] println!("compound at {} bytes", value.position()); let mut map: HashMap, NbtItem> = HashMap::new(); loop { let mut type_tag = [0_u8; 1]; _ = value.read(&mut type_tag).unwrap(); if type_tag == [0x00] { // End break; } // 读取 name // 直接调之前的方法读 let name = NbtValue::from_string(value).as_string().unwrap(); #[cfg(feature = "core_debug")] println!("compound type tag {:?} with name: {:?}", type_tag, name); // 读取 value let nbt_value: NbtItem = match type_tag { [0x01] => NbtItem::Value(NbtValue::from_i8(value)), [0x02] => NbtItem::Value(NbtValue::from_i16(value)), [0x03] => NbtItem::Value(NbtValue::from_i32(value)), [0x04] => NbtItem::Value(NbtValue::from_i64(value)), [0x05] => NbtItem::Value(NbtValue::from_f32(value)), [0x06] => NbtItem::Value(NbtValue::from_f64(value)), [0x07] => NbtItem::from(from_i8_array(value)), [0x08] => NbtItem::Value(NbtValue::from_string(value)), [0x09] => NbtItem::from(from_nbt_list(value)), [0x0A] => { let item = match from_compound(value) { NbtList::Compound(mut get_name, item) => { get_name = name.clone(); NbtList::Compound(get_name, item) } _ => panic!("WTF"), }; NbtItem::from(item) } [0x0B] => NbtItem::from(from_i32_array(value)), [0x0C] => NbtItem::from(from_i64_array(value)), _ => { panic!( "{}", format!( "WTF while reading Nbt Compound \ntype: {:?}\nreader pos: {:?}\nname: {:?}", type_tag, value.position(), name ) ) } }; // 读取完了,放进去 map.insert(name, nbt_value); #[cfg(feature = "core_debug")] println!("compound: {:?}", map); } NbtList::from((Arc::from(""), map)) } } use read_data::{from_compound, from_i32_array, from_i64_array, from_i8_array, from_nbt_list}; pub enum NbtStatus { /// 读取到了 End End, /// 继续中 Going(NbtItem), /// 读取错误 Error(std::io::Error), } /// NbtItem /// 完整的读取逻辑就在这里了 /// 来力 impl TryFrom> for NbtItem { type Error = std::io::Error; /// 完整逻辑~ fn try_from(in_value: Reader) -> Result { let mut value: Reader = in_value.clone(); let mut items: Vec = Vec::new(); #[cfg(feature = "debug")] println!("reader pos: {:?}", value.position()); loop { // 读取类型 let mut buff = [0_u8; 1]; _ = value.read(&mut buff).unwrap(); let name = NbtValue::from_string(&mut value).as_string().unwrap(); let type_code: NbtStatus = match buff { [0x00] => NbtStatus::End, [0x01] => NbtStatus::Going(NbtItem::Value(NbtValue::from_i8(&mut value))), [0x02] => NbtStatus::Going(NbtItem::Value(NbtValue::from_i16(&mut value))), [0x03] => NbtStatus::Going(NbtItem::Value(NbtValue::from_i32(&mut value))), [0x04] => NbtStatus::Going(NbtItem::Value(NbtValue::from_i64(&mut value))), [0x05] => NbtStatus::Going(NbtItem::Value(NbtValue::from_f32(&mut value))), [0x06] => NbtStatus::Going(NbtItem::Value(NbtValue::from_f64(&mut value))), [0x07] => NbtStatus::Going(NbtItem::from(from_i8_array(&mut value))), [0x08] => NbtStatus::Going(NbtItem::Value(NbtValue::from_string(&mut value))), [0x09] => NbtStatus::Going(NbtItem::from(from_nbt_list(&mut value))), [0x0A] => NbtStatus::Going(NbtItem::from(from_compound(&mut value))), [0x0B] => NbtStatus::Going(NbtItem::from(from_i32_array(&mut value))), [0x0C] => NbtStatus::Going(NbtItem::from(from_i64_array(&mut value))), _ => NbtStatus::Error(std::io::Error::new( std::io::ErrorKind::InvalidData, format!( "WTF while reading Nbt Item \ntype: {:?}\nreader pos: {:?}", buff, value.position() ), )), }; #[cfg(feature = "core_debug")] println!("==type_code: {:?} reader pos: {:?}", buff, value.position()); match type_code { NbtStatus::End => { break; } NbtStatus::Going(item) => { let item = match item { NbtItem::Array(NbtList::Compound(mut get_name, map)) => { get_name = name; NbtItem::Array(NbtList::Compound(get_name, map)) } _ => item, }; items.push(item); if !value.has_data_left().unwrap() { break; } } NbtStatus::Error(e) => { return Err(e); } } } // 理论上 长度应该为 2 if items.len() >= 3 { Ok(NbtItem::Array(NbtList::from(items))) } else { Ok(items[0].clone()) } } }