Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
rj00a committed Jun 9, 2024
1 parent 394ece3 commit 0d23682
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 335 deletions.
2 changes: 1 addition & 1 deletion crates/valence_anvil/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub enum RegionError {
#[error("invalid compression scheme number of {0}")]
InvalidCompressionScheme(u8),
#[error("failed to parse NBT: {0}")]
Nbt(#[from] valence_nbt::binary::Error),
Nbt(#[from] valence_nbt::Error),
#[error("not all chunk NBT data was read")]
TrailingNbtData,
#[error("oversized chunk")]
Expand Down
40 changes: 22 additions & 18 deletions crates/valence_nbt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
[package]
name = "valence_nbt"
description = "Minecraft's Named Binary Tag (NBT) format."
readme = "README.md"
documentation = "https://docs.rs/valence_nbt/"
license.workspace = true
keywords = ["nbt", "minecraft", "serialization"]
version = "0.8.0"
description = "Minecraft's Named Binary Tag (NBT) format."
edition.workspace = true
license.workspace = true
repository.workspace = true
keywords = ["nbt", "minecraft", "serialization"]
categories = ["data-structures", "game-development"]
rust-version = "1.78.0"

[lints]
workspace = true
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
binary = ["dep:byteorder", "dep:cesu8"]
java_string = ["dep:java_string"]
snbt = []
# When enabled, the order of fields in compounds are preserved.
preserve_order = ["dep:indexmap"]
serde = ["dep:serde", "dep:thiserror", "indexmap?/serde"]
valence_ident = ["dep:valence_ident"]

[dependencies]
byteorder = { workspace = true, optional = true }
cesu8 = { workspace = true, optional = true }
indexmap = { workspace = true, optional = true }
java_string = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
thiserror = { workspace = true, optional = true }
uuid = { workspace = true, optional = true }
valence_ident = { workspace = true, optional = true }
byteorder = { version = "1.5.0", optional = true }
cesu8 = { version = "1.1.0", optional = true }
indexmap = { version = "2.2.6", optional = true }
java_string = { version = "0.1.2", path = "../java_string", optional = true }
serde = { version = "1.0.200", features = ["derive"], optional = true }
thiserror = { version = "1.0.59", optional = true }
uuid = { version = "1.8.0", optional = true }
valence_ident = { version = "0.2.0-alpha.1", optional = true }

[dev-dependencies]
pretty_assertions.workspace = true
serde_json.workspace = true
pretty_assertions = "1.4.0"
serde_json = "1.0.116"

[lints]
workspace = true
14 changes: 0 additions & 14 deletions crates/valence_nbt/README.md

This file was deleted.

14 changes: 6 additions & 8 deletions crates/valence_nbt/src/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,34 @@
//!
//! let mut buf = vec![];
//!
//! to_binary(&c, &mut buf, "").unwrap();
//! to_binary(&mut buf, "", &c).unwrap();
//! ```

Check failure on line 22 in crates/valence_nbt/src/binary.rs

View workflow job for this annotation

GitHub Actions / Miri Tests

the trait bound `&str: std::io::Write` is not satisfied

Check failure on line 22 in crates/valence_nbt/src/binary.rs

View workflow job for this annotation

GitHub Actions / Miri Tests

the trait bound `valence_nbt::Compound: valence_nbt::binary::ToModifiedUtf8` is not satisfied

Check failure on line 22 in crates/valence_nbt/src/binary.rs

View workflow job for this annotation

GitHub Actions / Miri Tests

mismatched types
//!
//! Decode NBT data from its binary form.
//!
//! ```
//! use valence_nbt::{compound, from_binary, Compound};
//! use valence_nbt::{compound, from_binary, Compound, Value};
//!
//! let some_bytes = [10, 0, 0, 3, 0, 3, 105, 110, 116, 0, 0, 222, 173, 0];
//!
//! let expected_value = compound! {
//! "int" => 0xdead
//! };
//!
//! let (nbt, root_name) = from_binary(&mut some_bytes.as_slice()).unwrap();
//! let (root_name, nbt) = from_binary(&mut some_bytes.as_slice()).unwrap().unwrap();
//!

Check failure on line 36 in crates/valence_nbt/src/binary.rs

View workflow job for this annotation

GitHub Actions / Miri Tests

no method named `unwrap` found for tuple `(valence_nbt::Compound<_>, _)` in the current scope
//! assert_eq!(nbt, expected_value);
//! assert_eq!(nbt, Value::from(expected_value));
//! assert_eq!(root_name, "");
//! ```
mod decode;
mod encode;
mod error;
mod modified_utf8;
#[cfg(test)]
mod tests;

pub use decode::{from_binary, FromModifiedUtf8, FromModifiedUtf8Error};
pub use encode::{to_binary, written_size, ToModifiedUtf8};
pub use error::*;
pub use decode::*;
pub use encode::*;

use crate::Tag;

Expand Down
3 changes: 1 addition & 2 deletions crates/valence_nbt/src/binary/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ use std::{fmt, mem};

use byteorder::{BigEndian, ReadBytesExt};

use super::{Error, Result};
use crate::tag::Tag;
use crate::{Compound, List, Value};
use crate::{Compound, Error, List, Result, Value};

/// Decodes uncompressed NBT binary data from the provided slice.
///
Expand Down
4 changes: 2 additions & 2 deletions crates/valence_nbt/src/binary/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use std::io::Write;

use byteorder::{BigEndian, WriteBytesExt};

use super::{modified_utf8, Error, Result};
use super::modified_utf8;
use crate::conv::i8_slice_as_u8_slice;
use crate::tag::Tag;
use crate::{Compound, List, Value};
use crate::{Compound, Error, List, Result, Value};

/// Encodes uncompressed NBT binary data to the provided writer.
///
Expand Down
12 changes: 6 additions & 6 deletions crates/valence_nbt/src/binary/modified_utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub(crate) fn write_modified_utf8(mut writer: impl Write, text: &str) -> io::Res
while i < bytes.len() {
match bytes[i] {
0 => {
writer.write_u16::<BigEndian>(0xc080)?;
writer.write_u16::<BigEndian>(0xC080)?;
i += 1;
}
b @ 1..=127 => {
Expand All @@ -35,8 +35,8 @@ pub(crate) fn write_modified_utf8(mut writer: impl Write, text: &str) -> io::Res
let s = unsafe { from_utf8_unchecked(&bytes[i..i + w]) };
let c = s.chars().next().unwrap() as u32 - 0x10000;

let s0 = ((c >> 10) as u16) | 0xd800;
let s1 = ((c & 0x3ff) as u16) | 0xdc00;
let s0 = ((c >> 10) as u16) | 0xD800;
let s1 = ((c & 0x3FF) as u16) | 0xDC00;

writer.write_all(encode_surrogate(s0).as_slice())?;
writer.write_all(encode_surrogate(s1).as_slice())?;
Expand All @@ -62,13 +62,13 @@ const fn utf8_char_width(first_byte: u8) -> usize {
4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];

UTF8_CHAR_WIDTH[first_byte as usize] as _
UTF8_CHAR_WIDTH[first_byte as usize] as usize
}

fn encode_surrogate(surrogate: u16) -> [u8; 3] {
debug_assert!((0xd800..=0xdfff).contains(&surrogate));
debug_assert!((0xD800..=0xDFFF).contains(&surrogate));

const TAG_CONT_U8: u8 = 0b1000_0000u8;
const TAG_CONT_U8: u8 = 0b1000_0000_u8;
[
0b11100000 | ((surrogate & 0b11110000_00000000) >> 12) as u8,
TAG_CONT_U8 | ((surrogate & 0b00001111_11000000) >> 6) as u8,
Expand Down
27 changes: 8 additions & 19 deletions crates/valence_nbt/src/binary/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::binary::written_size;
use crate::tag::Tag;
use crate::{compound, from_binary, to_binary, Compound, List, Value};

Expand All @@ -10,26 +9,26 @@ fn round_trip() {

let compound = example_compound();

to_binary(&compound, &mut buf, ROOT_NAME).unwrap();
to_binary(&mut buf, ROOT_NAME, &compound).unwrap();

println!("{buf:?}");

let (decoded, root_name) = crate::from_binary(&mut buf.as_slice()).unwrap();
let (root_name, decoded) = from_binary(&mut buf.as_slice()).unwrap().unwrap();

assert_eq!(root_name, ROOT_NAME);
assert_eq!(compound, decoded);
assert_eq!(Value::from(compound), decoded);
}

#[test]
fn check_min_sizes() {
fn check(min_val: Value, expected_size: usize) {
/// TAG_Compound + root name + field tag + field name + TAG_End
/// `TAG_Compound` + root name + field tag + field name + `TAG_End`
const COMPOUND_OVERHEAD: usize = 1 + 2 + 1 + 2 + 1;

let dbg = format!("{min_val:?}");
let mut buf = vec![];

to_binary(&compound!("" => min_val), &mut buf, "").unwrap();
to_binary(&mut buf, "", &compound!("" => min_val)).unwrap();

assert_eq!(
expected_size,
Expand All @@ -45,7 +44,7 @@ fn check_min_sizes() {
check(Value::Float(0.0), 4);
check(Value::Double(0.0), 8);
check(Value::ByteArray([].into()), 4);
check(Value::String("".into()), 2);
check(Value::String(String::new()), 2);
check(Value::List(Vec::<i32>::new().into()), 5);
check(Value::Compound(compound!()), 1);
check(Value::IntArray([].into()), 4);
Expand All @@ -66,7 +65,7 @@ fn deeply_nested_compound_decode() {
buf.push(Tag::End as u8); // End root compound

// Should not overflow the stack
let _ = from_binary::<String>(&mut buf.as_slice());
let _ = from_binary::<_, String>(&mut buf.as_slice());
}

#[test]
Expand All @@ -85,17 +84,7 @@ fn deeply_nested_list_decode() {
buf.push(Tag::End as u8); // End root compound

// Should not overflow the stack
let _ = from_binary::<String>(&mut buf.as_slice());
}

#[test]
fn correct_length() {
let c = example_compound();

let mut buf = vec![];
to_binary(&c, &mut buf, "abc").unwrap();

assert_eq!(written_size(&c, "abc"), buf.len());
let _ = from_binary::<_, String>(&mut buf.as_slice());
}

fn example_compound() -> Compound {
Expand Down
Loading

0 comments on commit 0d23682

Please sign in to comment.