Compare commits

..

No commits in common. "c367042d5809a2943248c0c4fabddb6c5ebcad1d" and "393083891c3dc5bfec696a863781cd248db6c419" have entirely different histories.

6 changed files with 20 additions and 403 deletions

View File

@ -9,11 +9,11 @@
- [x] JavaNetAfter1_20_2
- [x] BedrockDisk
- [x] BedrockNetVarInt
- [x] 写入
- [ ] 写入
- [x] Java
- [x] JavaNetAfter1_20_2
- [x] BedrockDisk
- [x] BedrockNetVarInt
- [ ] BedrockDisk
- [ ] BedrockNetVarInt
- [ ] `Serde` 支持
- [ ] `Serialize`
- [ ] `Deserialize`

View File

@ -200,9 +200,7 @@ fn test_v5(mut data: Vec<u8>) {
std::thread::sleep(std::time::Duration::from_secs(1));
test_lib!(
{
let _nbt_data = shen_nbt5::NbtValue::from_binary::<shen_nbt5::nbt_version::Java>(
data.as_mut_slice(),
);
let _nbt_data = shen_nbt5::NbtValue::from_binary(data.as_mut_slice());
},
"nbt v5",
len
@ -258,10 +256,7 @@ fn cli_read_test() {
std::thread::sleep(std::time::Duration::from_secs(1));
let start_time = std::time::Instant::now();
// let nbt_data = shen_nbt4::Value::from_vec(data);
let nbt_data =
shen_nbt5::NbtValue::from_binary::<shen_nbt5::nbt_version::Java>(data.as_mut_slice())
.unwrap();
let nbt_data = shen_nbt5::NbtValue::from_binary(data.as_mut_slice());
let end_time = std::time::Instant::now();
println!("=== shen nbt 5 ===");
println!("time: {:?}", end_time - start_time);

View File

@ -1,6 +1,6 @@
[package]
name = "shen-nbt5"
version = "0.4.0"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -29,13 +29,13 @@ impl nbt_version::NbtReadTrait for nbt_version::Java {
#[inline]
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
let len = reader.read_be_i32() as usize;
let value = reader.read_be_i32_array(len);
let value = reader.read_i32_array(len);
Ok(value)
}
#[inline]
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
let len = reader.read_be_i32() as usize;
let value = reader.read_be_i64_array(len);
let value = reader.read_i64_array(len);
Ok(value)
}
#[inline]
@ -159,13 +159,13 @@ impl NbtReadTrait for BedrockDisk {
#[inline]
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
let len = reader.read_le_i32() as usize;
let value = reader.read_le_i32_array(len);
let value = reader.read_i32_array(len);
Ok(value)
}
#[inline]
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
let len = reader.read_le_i32() as usize;
let value = reader.read_le_i64_array(len);
let value = reader.read_i64_array(len);
Ok(value)
}
#[inline]
@ -256,12 +256,12 @@ impl NbtReadTrait for BedrockNetVarInt {
}
fn read_i32_array(reader: &mut NbtReader) -> NbtResult<Vec<i32>> {
let len = reader.read_zigzag_var_i32()? as usize;
let value = reader.read_le_i32_array(len);
let value = reader.read_i32_array(len);
Ok(value)
}
fn read_i64_array(reader: &mut NbtReader) -> NbtResult<Vec<i64>> {
let len = reader.read_zigzag_var_i32()? as usize;
let value = reader.read_le_i64_array(len);
let value = reader.read_i64_array(len);
Ok(value)
}
fn read_compound(reader: &mut NbtReader) -> NbtResult<Vec<(String, NbtValue)>> {
@ -727,7 +727,7 @@ impl NbtReader<'_> {
///
/// 长度溢出会导致 UB
#[inline]
pub unsafe fn read_be_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
pub unsafe fn read_i32_array_unsafe(&mut self, len: usize) -> Vec<i32> {
let value =
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i32, len);
let mut value = value.to_vec();
@ -743,7 +743,7 @@ impl NbtReader<'_> {
///
/// 长度溢出会导致 panic
#[inline]
pub fn read_be_i32_array(&mut self, len: usize) -> Vec<i32> {
pub fn read_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_be_bytes(n[0..4].try_into().unwrap()))
@ -757,7 +757,7 @@ impl NbtReader<'_> {
///
/// 长度溢出会导致 UB
#[inline]
pub unsafe fn read_be_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
pub unsafe fn read_i64_array_unsafe(&mut self, len: usize) -> Vec<i64> {
let value =
std::slice::from_raw_parts(self.data[self.cursor..].as_ptr() as *const i64, len);
let mut value = value.to_vec();
@ -773,7 +773,7 @@ impl NbtReader<'_> {
///
/// 长度溢出会导致 panic
#[inline]
pub fn read_be_i64_array(&mut self, len: usize) -> Vec<i64> {
pub fn read_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_be_bytes(n[0..8].try_into().unwrap()))
@ -781,48 +781,6 @@ impl NbtReader<'_> {
self.cursor += len * 8;
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 字符串
///
/// # 安全性

View File

@ -260,9 +260,9 @@ mod unsafe_test {
let mut value = gen_datas(4 * 100);
let mut reader = NbtReader::new(&mut value);
unsafe {
let value = reader.read_be_i32_array_unsafe(100);
let value = reader.read_i32_array_unsafe(100);
reader.roll_back(100 * 4);
let safe_value = reader.read_be_i32_array(100);
let safe_value = reader.read_i32_array(100);
assert_eq!(value, safe_value);
assert_eq!(reader.cursor, 100 * 4);
}
@ -273,9 +273,9 @@ mod unsafe_test {
let mut value = gen_datas(8 * 100);
let mut reader = NbtReader::new(&mut value);
unsafe {
let value = reader.read_be_i64_array_unsafe(100);
let value = reader.read_i64_array_unsafe(100);
reader.roll_back(100 * 8);
let safe_value = reader.read_be_i64_array(100);
let safe_value = reader.read_i64_array(100);
assert_eq!(value, safe_value);
assert_eq!(reader.cursor, 100 * 8);
}

View File

@ -202,339 +202,3 @@ impl NbtWriteTrait for JavaNetAfter1_20_2 {
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)
}
}