理论上好了
This commit is contained in:
parent
393083891c
commit
5073d9780a
@ -29,13 +29,13 @@ impl nbt_version::NbtReadTrait for nbt_version::Java {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
let len = reader.read_be_i32() as usize;
|
let len = reader.read_be_i32() as usize;
|
||||||
let value = reader.read_i32_array(len);
|
let value = reader.read_be_i32_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
let len = reader.read_be_i32() as usize;
|
let len = reader.read_be_i32() as usize;
|
||||||
let value = reader.read_i64_array(len);
|
let value = reader.read_be_i64_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -159,13 +159,13 @@ impl NbtReadTrait for BedrockDisk {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
let len = reader.read_le_i32() as usize;
|
let len = reader.read_le_i32() as usize;
|
||||||
let value = reader.read_i32_array(len);
|
let value = reader.read_le_i32_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
let len = reader.read_le_i32() as usize;
|
let len = reader.read_le_i32() as usize;
|
||||||
let value = reader.read_i64_array(len);
|
let value = reader.read_le_i64_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -256,12 +256,12 @@ impl NbtReadTrait for BedrockNetVarInt {
|
|||||||
}
|
}
|
||||||
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
|
||||||
let len = reader.read_zigzag_var_i32()? as usize;
|
let len = reader.read_zigzag_var_i32()? as usize;
|
||||||
let value = reader.read_i32_array(len);
|
let value = reader.read_le_i32_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
|
||||||
let len = reader.read_zigzag_var_i32()? as usize;
|
let len = reader.read_zigzag_var_i32()? as usize;
|
||||||
let value = reader.read_i64_array(len);
|
let value = reader.read_le_i64_array(len);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
|
||||||
@ -727,7 +727,7 @@ impl NbtReader<'_> {
|
|||||||
///
|
///
|
||||||
/// 长度溢出会导致 UB
|
/// 长度溢出会导致 UB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
|
pub unsafe fn read_be_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
|
||||||
let value =
|
let value =
|
||||||
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len);
|
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len);
|
||||||
let mut value = value.to_vec();
|
let mut value = value.to_vec();
|
||||||
@ -743,7 +743,7 @@ impl NbtReader<'_> {
|
|||||||
///
|
///
|
||||||
/// 长度溢出会导致 panic
|
/// 长度溢出会导致 panic
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_i32_array(&mut self, len: usize) -> Vec<i32> {
|
pub fn read_be_i32_array(&mut self, len: usize) -> Vec<i32> {
|
||||||
let value = self.data[self.cursor..self.cursor + len * 4]
|
let value = self.data[self.cursor..self.cursor + len * 4]
|
||||||
.chunks_exact(4)
|
.chunks_exact(4)
|
||||||
.map(|n| i32::from_be_bytes(n[0..4].try_into().unwrap()))
|
.map(|n| i32::from_be_bytes(n[0..4].try_into().unwrap()))
|
||||||
@ -757,7 +757,7 @@ impl NbtReader<'_> {
|
|||||||
///
|
///
|
||||||
/// 长度溢出会导致 UB
|
/// 长度溢出会导致 UB
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
|
pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
|
||||||
let value =
|
let value =
|
||||||
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i64, len);
|
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i64, len);
|
||||||
let mut value = value.to_vec();
|
let mut value = value.to_vec();
|
||||||
@ -773,7 +773,7 @@ impl NbtReader<'_> {
|
|||||||
///
|
///
|
||||||
/// 长度溢出会导致 panic
|
/// 长度溢出会导致 panic
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_i64_array(&mut self, len: usize) -> Vec<i64> {
|
pub fn read_be_i64_array(&mut self, len: usize) -> Vec<i64> {
|
||||||
let value = self.data[self.cursor..self.cursor + len * 8]
|
let value = self.data[self.cursor..self.cursor + len * 8]
|
||||||
.chunks_exact(8)
|
.chunks_exact(8)
|
||||||
.map(|n| i64::from_be_bytes(n[0..8].try_into().unwrap()))
|
.map(|n| i64::from_be_bytes(n[0..8].try_into().unwrap()))
|
||||||
@ -781,6 +781,48 @@ impl NbtReader<'_> {
|
|||||||
self.cursor += len * 8;
|
self.cursor += len * 8;
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
/// 读取指定长度的 le i16 数组
|
||||||
|
///
|
||||||
|
/// # 安全性
|
||||||
|
///
|
||||||
|
/// 长度溢出会导致 panic
|
||||||
|
#[inline]
|
||||||
|
pub fn read_le_i16_array(&mut self, len: usize) -> Vec<i16> {
|
||||||
|
let value = self.data[self.cursor..self.cursor + len * 2]
|
||||||
|
.chunks_exact(2)
|
||||||
|
.map(|n| i16::from_le_bytes(n[0..2].try_into().unwrap()))
|
||||||
|
.collect();
|
||||||
|
self.cursor += len * 2;
|
||||||
|
value
|
||||||
|
}
|
||||||
|
/// 读取指定长度的 le i32 数组
|
||||||
|
///
|
||||||
|
/// # 安全性
|
||||||
|
///
|
||||||
|
/// 长度溢出会导致 panic
|
||||||
|
#[inline]
|
||||||
|
pub fn read_le_i32_array(&mut self, len: usize) -> Vec<i32> {
|
||||||
|
let value = self.data[self.cursor..self.cursor + len * 4]
|
||||||
|
.chunks_exact(4)
|
||||||
|
.map(|n| i32::from_le_bytes(n[0..4].try_into().unwrap()))
|
||||||
|
.collect();
|
||||||
|
self.cursor += len * 4;
|
||||||
|
value
|
||||||
|
}
|
||||||
|
/// 读取指定长度的 le i64 数组
|
||||||
|
///
|
||||||
|
/// # 安全性
|
||||||
|
///
|
||||||
|
/// 长度溢出会导致 panic
|
||||||
|
#[inline]
|
||||||
|
pub fn read_le_i64_array(&mut self, len: usize) -> Vec<i64> {
|
||||||
|
let value = self.data[self.cursor..self.cursor + len * 8]
|
||||||
|
.chunks_exact(8)
|
||||||
|
.map(|n| i64::from_le_bytes(n[0..8].try_into().unwrap()))
|
||||||
|
.collect();
|
||||||
|
self.cursor += len * 8;
|
||||||
|
value
|
||||||
|
}
|
||||||
/// 读取指定长度的 utf-8 字符串
|
/// 读取指定长度的 utf-8 字符串
|
||||||
///
|
///
|
||||||
/// # 安全性
|
/// # 安全性
|
||||||
|
@ -260,9 +260,9 @@ mod unsafe_test {
|
|||||||
let mut value = gen_datas(4 * 100);
|
let mut value = gen_datas(4 * 100);
|
||||||
let mut reader = NbtReader::new(&mut value);
|
let mut reader = NbtReader::new(&mut value);
|
||||||
unsafe {
|
unsafe {
|
||||||
let value = reader.read_i32_array_unsafe(100);
|
let value = reader.read_be_i32_array_unsafe(100);
|
||||||
reader.roll_back(100 * 4);
|
reader.roll_back(100 * 4);
|
||||||
let safe_value = reader.read_i32_array(100);
|
let safe_value = reader.read_be_i32_array(100);
|
||||||
assert_eq!(value, safe_value);
|
assert_eq!(value, safe_value);
|
||||||
assert_eq!(reader.cursor, 100 * 4);
|
assert_eq!(reader.cursor, 100 * 4);
|
||||||
}
|
}
|
||||||
@ -273,9 +273,9 @@ mod unsafe_test {
|
|||||||
let mut value = gen_datas(8 * 100);
|
let mut value = gen_datas(8 * 100);
|
||||||
let mut reader = NbtReader::new(&mut value);
|
let mut reader = NbtReader::new(&mut value);
|
||||||
unsafe {
|
unsafe {
|
||||||
let value = reader.read_i64_array_unsafe(100);
|
let value = reader.read_be_i64_array_unsafe(100);
|
||||||
reader.roll_back(100 * 8);
|
reader.roll_back(100 * 8);
|
||||||
let safe_value = reader.read_i64_array(100);
|
let safe_value = reader.read_be_i64_array(100);
|
||||||
assert_eq!(value, safe_value);
|
assert_eq!(value, safe_value);
|
||||||
assert_eq!(reader.cursor, 100 * 8);
|
assert_eq!(reader.cursor, 100 * 8);
|
||||||
}
|
}
|
||||||
|
@ -202,3 +202,339 @@ impl NbtWriteTrait for JavaNetAfter1_20_2 {
|
|||||||
Ok(buff)
|
Ok(buff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 比较痛苦的一集
|
||||||
|
impl NbtWriteTrait for BedrockDisk {
|
||||||
|
#[inline]
|
||||||
|
fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
|
||||||
|
// 写入长度
|
||||||
|
writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
|
||||||
|
// 写入数据
|
||||||
|
writer.extend_from_slice(data.iter().map(|x| *x as u8).collect::<Vec<u8>>().as_slice());
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) {
|
||||||
|
// 写入长度
|
||||||
|
writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
|
||||||
|
// 写入数据
|
||||||
|
writer.extend_from_slice(
|
||||||
|
&data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 4]>>().concat(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) {
|
||||||
|
// 写入长度
|
||||||
|
writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
|
||||||
|
// 写入数据
|
||||||
|
writer.extend_from_slice(
|
||||||
|
&data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 8]>>().concat(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn write_nbt_string(writer: &mut Vec<u8>, data: &str) {
|
||||||
|
// 写入长度
|
||||||
|
writer.extend_from_slice(&(data.len() as u16).to_le_bytes());
|
||||||
|
// 写入数据
|
||||||
|
writer.extend_from_slice(data.as_bytes());
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
|
||||||
|
if data.is_empty() {
|
||||||
|
// 写入一个空的 tag
|
||||||
|
writer.extend_from_slice(&0i8.to_le_bytes());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// 遍历检查一遍所有的 tag 是否一致
|
||||||
|
let tag = data.first().unwrap().tag();
|
||||||
|
if !data.iter().all(|x| x.tag() == tag) {
|
||||||
|
return Err(NbtError::ListTypeNotSame(data.iter().map(|x| x.tag()).collect()));
|
||||||
|
}
|
||||||
|
// 写入 tag
|
||||||
|
writer.push(tag);
|
||||||
|
// 写入长度
|
||||||
|
writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
|
||||||
|
// 写入数据
|
||||||
|
for i in data {
|
||||||
|
match i {
|
||||||
|
NbtValue::Byte(x) => writer.push(*x as u8),
|
||||||
|
NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
|
||||||
|
NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
|
||||||
|
NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
|
||||||
|
NbtValue::String(x) => Self::write_nbt_string(writer, x),
|
||||||
|
NbtValue::List(x) => Self::write_list(writer, x)?,
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
Self::write_compound(writer, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn write_compound(
|
||||||
|
writer: &mut Vec<u8>,
|
||||||
|
name: Option<&String>,
|
||||||
|
data: &[(String, NbtValue)],
|
||||||
|
) -> NbtResult<()> {
|
||||||
|
// 写入自己的名字
|
||||||
|
Self::write_nbt_string(writer, name.unwrap_or(&"".to_string()));
|
||||||
|
for (key, value) in data {
|
||||||
|
// 写入 tag
|
||||||
|
writer.push(value.tag());
|
||||||
|
// 写入 key
|
||||||
|
Self::write_nbt_string(writer, key);
|
||||||
|
// 写入 value
|
||||||
|
match value {
|
||||||
|
NbtValue::Byte(x) => writer.push(*x as u8),
|
||||||
|
NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
|
||||||
|
NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
|
||||||
|
NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
|
||||||
|
NbtValue::String(x) => Self::write_nbt_string(writer, x),
|
||||||
|
NbtValue::List(x) => Self::write_list(writer, x)?,
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
Self::write_compound(writer, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 写入结束 tag
|
||||||
|
writer.push(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
|
||||||
|
// 写入 tag
|
||||||
|
match value {
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
buff.push(value.tag());
|
||||||
|
Self::write_compound(buff, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
NbtValue::List(data) => {
|
||||||
|
buff.push(value.tag());
|
||||||
|
Self::write_list(buff, data)?
|
||||||
|
}
|
||||||
|
x => return Err(NbtError::WrongRootType(x.tag())),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
|
||||||
|
// 写入 tag
|
||||||
|
buff.push(value.tag());
|
||||||
|
// 写入 key
|
||||||
|
Self::write_nbt_string(buff, name);
|
||||||
|
// 写入 value
|
||||||
|
Self::write_to(value, buff)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_binary(value: &NbtValue) -> NbtResult<Vec<u8>> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
BedrockDisk::write_to(value, &mut buff)?;
|
||||||
|
Ok(buff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var_i32_to_bytes(value: i32) -> Vec<u8> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
let mut value = value;
|
||||||
|
loop {
|
||||||
|
let mut temp = (value & 0b01111111) as u8;
|
||||||
|
value >>= 7;
|
||||||
|
if value != 0 {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buff.push(temp);
|
||||||
|
if value == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn var_i64_to_bytes(value: i64) -> Vec<u8> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
let mut value = value;
|
||||||
|
loop {
|
||||||
|
let mut temp = (value & 0b01111111) as u8;
|
||||||
|
value >>= 7;
|
||||||
|
if value != 0 {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buff.push(temp);
|
||||||
|
if value == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zigzag_var_i32_to_bytes(value: i32) -> Vec<u8> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
let mut value = (value << 1) ^ (value >> 31);
|
||||||
|
loop {
|
||||||
|
let mut temp = (value & 0b01111111) as u8;
|
||||||
|
value >>= 7;
|
||||||
|
if value != 0 {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buff.push(temp);
|
||||||
|
if value == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zigzag_var_i64_to_bytes(value: i64) -> Vec<u8> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
let mut value = (value << 1) ^ (value >> 63);
|
||||||
|
loop {
|
||||||
|
let mut temp = (value & 0b01111111) as u8;
|
||||||
|
value >>= 7;
|
||||||
|
if value != 0 {
|
||||||
|
temp |= 0b10000000;
|
||||||
|
}
|
||||||
|
buff.push(temp);
|
||||||
|
if value == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 最痛苦的一集
|
||||||
|
impl NbtWriteTrait for BedrockNetVarInt {
|
||||||
|
fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
|
||||||
|
// zigzag var i32
|
||||||
|
writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
|
||||||
|
writer.extend_from_slice(data.iter().map(|x| *x as u8).collect::<Vec<u8>>().as_slice());
|
||||||
|
}
|
||||||
|
fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) {
|
||||||
|
// zigzag var i32
|
||||||
|
writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
|
||||||
|
writer.extend_from_slice(
|
||||||
|
&data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 4]>>().concat(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) {
|
||||||
|
// zigzag var i32
|
||||||
|
writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
|
||||||
|
writer.extend_from_slice(
|
||||||
|
&data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 8]>>().concat(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn write_nbt_string(writer: &mut Vec<u8>, data: &str) {
|
||||||
|
// zigzag var i32
|
||||||
|
writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
|
||||||
|
writer.extend_from_slice(data.as_bytes());
|
||||||
|
}
|
||||||
|
fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
|
||||||
|
if data.is_empty() {
|
||||||
|
// 写入一个空的 tag
|
||||||
|
writer.extend_from_slice(&0i8.to_le_bytes());
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// 遍历检查一遍所有的 tag 是否一致
|
||||||
|
let tag = data.first().unwrap().tag();
|
||||||
|
if !data.iter().all(|x| x.tag() == tag) {
|
||||||
|
return Err(NbtError::ListTypeNotSame(data.iter().map(|x| x.tag()).collect()));
|
||||||
|
}
|
||||||
|
// 写入 tag
|
||||||
|
writer.push(tag);
|
||||||
|
// zigzag var i32
|
||||||
|
writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
|
||||||
|
// 写入数据
|
||||||
|
for i in data {
|
||||||
|
match i {
|
||||||
|
NbtValue::Byte(x) => writer.push(*x as u8),
|
||||||
|
NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
|
||||||
|
NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
|
||||||
|
NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
|
||||||
|
NbtValue::String(x) => Self::write_nbt_string(writer, x),
|
||||||
|
NbtValue::List(x) => Self::write_list(writer, x)?,
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
Self::write_compound(writer, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn write_compound(
|
||||||
|
writer: &mut Vec<u8>,
|
||||||
|
name: Option<&String>,
|
||||||
|
data: &[(String, NbtValue)],
|
||||||
|
) -> NbtResult<()> {
|
||||||
|
// 写入自己的名字
|
||||||
|
Self::write_nbt_string(writer, name.unwrap_or(&"".to_string()));
|
||||||
|
for (key, value) in data {
|
||||||
|
// 写入 tag
|
||||||
|
writer.push(value.tag());
|
||||||
|
// 写入 key
|
||||||
|
Self::write_nbt_string(writer, key);
|
||||||
|
// 写入 value
|
||||||
|
match value {
|
||||||
|
NbtValue::Byte(x) => writer.push(*x as u8),
|
||||||
|
NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
|
||||||
|
NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
|
||||||
|
NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
|
||||||
|
NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
|
||||||
|
NbtValue::String(x) => Self::write_nbt_string(writer, x),
|
||||||
|
NbtValue::List(x) => Self::write_list(writer, x)?,
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
Self::write_compound(writer, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 写入结束 tag
|
||||||
|
writer.push(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
|
||||||
|
// 写入 tag
|
||||||
|
match value {
|
||||||
|
NbtValue::Compound(name, data) => {
|
||||||
|
buff.push(value.tag());
|
||||||
|
Self::write_compound(buff, name.as_ref(), data)?
|
||||||
|
}
|
||||||
|
NbtValue::List(data) => {
|
||||||
|
buff.push(value.tag());
|
||||||
|
Self::write_list(buff, data)?
|
||||||
|
}
|
||||||
|
x => return Err(NbtError::WrongRootType(x.tag())),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
|
||||||
|
// 写入 tag
|
||||||
|
buff.push(value.tag());
|
||||||
|
// 写入 key
|
||||||
|
Self::write_nbt_string(buff, name);
|
||||||
|
// 写入 value
|
||||||
|
Self::write_to(value, buff)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn to_binary(value: &NbtValue) -> NbtResult<Vec<u8>> {
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
BedrockNetVarInt::write_to(value, &mut buff)?;
|
||||||
|
Ok(buff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user