This commit is contained in:
2025-05-19 13:51:49 +02:00
parent 31d04ac789
commit 9d495ba239
5 changed files with 307 additions and 1 deletions

4
.gitignore vendored
View File

@@ -15,3 +15,7 @@ target/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# Added by cargo
/target

7
Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "nbt"
version = "0.1.0"

6
Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[package]
name = "nbt"
version = "0.1.0"
edition = "2024"
[dependencies]

136
src/lib.rs Normal file
View File

@@ -0,0 +1,136 @@
use std::collections::HashMap;
mod test;
// Id of nbt
pub type TagId = u8;
// All the types of nbt
#[derive(PartialEq,Clone,Debug,)]
pub enum Tag {
End,
Byte {
name: Option<String>,
value: i8,
},
Short {
name: Option<String>,
value: i16,
},
Int {
name: Option<String>,
value: i32,
},
Long {
name: Option<String>,
value: i64,
},
Float {
name: Option<String>,
value: f32,
},
Double {
name: Option<String>,
value: f64,
},
ByteArray {
name: Option<String>,
value: Vec<u8>,
},
String {
name: Option<String>,
value: String,
},
List {
name: Option<String>,
element_id: TagId,
elements: Vec<Tag>,
},
Compound {
name: Option<String>,
entries: HashMap<String, Tag>,
},
IntArray {
name: Option<String>,
value: Vec<i32>,
},
LongArray {
name: Option<String>,
value: Vec<i64>,
},
}
impl Tag {
pub fn new_byte(name: impl Into<String>, v: i8) -> Tag {
Tag::Byte {
name: Some(name.into()),
value: v,
}
}
pub fn new_short(name: impl Into<String>, v: i16) -> Tag {
Tag::Short {
name: Some(name.into()),
value: v,
}
}
pub fn new_int(name: impl Into<String>, v: i32) -> Tag {
Tag::Int {
name: Some(name.into()),
value: v,
}
}
pub fn new_long(name: impl Into<String>, v: i64) -> Tag {
Tag::Long {
name: Some(name.into()),
value: v,
}
}
pub fn new_float(name: impl Into<String>, v: f32) -> Tag {
Tag::Float {
name: Some(name.into()),
value: v,
}
}
pub fn new_double(name: impl Into<String>, v: f64) -> Tag {
Tag::Double {
name: Some(name.into()),
value: v,
}
}
pub fn new_ByteArray(name: impl Into<String>, v: Vec<u8>) -> Tag {
Tag::ByteArray {
name: Some(name.into()),
value: v,
}
}
pub fn new_string(name: impl Into<String>, v: impl Into<String>) -> Tag {
Tag::String {
name: Some(name.into()),
value: v.into(),
}
}
pub fn new_list(name: impl Into<String>, element_id: TagId, elements: Vec<Tag>) -> Tag {
Tag::List {
name: Some(name.into()),
element_id,
elements,
}
}
pub fn new_compound(name: impl Into<String>) -> Tag {
Tag::Compound {
name: Some(name.into()),
entries: HashMap::new(),
}
}
pub fn new_int_array(name: impl Into<String>, v: Vec<i32>) -> Tag {
Tag::IntArray {
name: Some(name.into()),
value: v,
}
}
pub fn new_long_array(name: impl Into<String>, v: Vec<i64>) -> Tag {
Tag::LongArray {
name: Some(name.into()),
value: v,
}
}
}

153
src/test.rs Normal file
View File

@@ -0,0 +1,153 @@
#[cfg(test)]
mod tests {
use crate::Tag;
#[test]
fn new_byte_tag() {
let tag = Tag::new_byte("health", 20);
match tag {
Tag::Byte { name, value } => {
assert_eq!(name.unwrap(), "health");
assert_eq!(value, 20);
}
_ => panic!("Expected Byte tag"),
}
}
#[test]
fn new_short_tag() {
let tag = Tag::new_short("optLevel", 3);
match tag {
Tag::Short { name, value } => {
assert_eq!(name.unwrap(), "optLevel");
assert_eq!(value, 3);
}
_ => panic!("Expected Short tag"),
}
}
#[test]
fn new_int_tag() {
let tag = Tag::new_int("xPos", 100);
match tag {
Tag::Int { name, value } => {
assert_eq!(name.unwrap(), "xPos");
assert_eq!(value, 100);
}
_ => panic!("Expected Int tag"),
}
}
#[test]
fn new_long_tag() {
let tag = Tag::new_long("timestamp", 1_620_000_000_000);
match tag {
Tag::Long { name, value } => {
assert_eq!(name.unwrap(), "timestamp");
assert_eq!(value, 1_620_000_000_000);
}
_ => panic!("Expected Long tag"),
}
}
#[test]
fn new_float_tag() {
let tag = Tag::new_float("speed", 0.5);
match tag {
Tag::Float { name, value } => {
assert_eq!(name.unwrap(), "speed");
assert!((value - 0.5).abs() < f32::EPSILON);
}
_ => panic!("Expected Float tag"),
}
}
#[test]
fn new_double_tag() {
let tag = Tag::new_double("gravity", 9.81);
match tag {
Tag::Double { name, value } => {
assert_eq!(name.unwrap(), "gravity");
assert!((value - 9.81).abs() < f64::EPSILON);
}
_ => panic!("Expected Double tag"),
}
}
#[test]
fn new_byte_array_tag() {
let data = vec![1u8, 2, 3, 4];
let tag = Tag::new_ByteArray("blocks", data.clone());
match tag {
Tag::ByteArray { name, value } => {
assert_eq!(name.unwrap(), "blocks");
assert_eq!(value, data);
}
_ => panic!("Expected ByteArray tag"),
}
}
#[test]
fn new_string_tag() {
let tag = Tag::new_string("name", "Steve");
match tag {
Tag::String { name, value } => {
assert_eq!(name.unwrap(), "name");
assert_eq!(value, "Steve");
}
_ => panic!("Expected String tag"),
}
}
#[test]
fn new_list_tag() {
let elements = vec![Tag::new_int("", 1), Tag::new_int("", 2)];
let tag = Tag::new_list("nums", 3, elements.clone());
match tag {
Tag::List { name, element_id, elements: elems } => {
assert_eq!(name.unwrap(), "nums");
assert_eq!(element_id, 3);
assert_eq!(elems, elements);
}
_ => panic!("Expected List tag"),
}
}
#[test]
fn new_compound_tag() {
let tag = Tag::new_compound("Level");
match tag {
Tag::Compound { name, entries } => {
assert_eq!(name.unwrap(), "Level");
assert!(entries.is_empty());
}
_ => panic!("Expected Compound tag"),
}
}
#[test]
fn new_int_array_tag() {
let data = vec![1i32, 2, 3];
let tag = Tag::new_int_array("palette", data.clone());
match tag {
Tag::IntArray { name, value } => {
assert_eq!(name.unwrap(), "palette");
assert_eq!(value, data);
}
_ => panic!("Expected IntArray tag"),
}
}
#[test]
fn new_long_array_tag() {
let data = vec![100i64, 200];
let tag = Tag::new_long_array("timestamps", data.clone());
match tag {
Tag::LongArray { name, value } => {
assert_eq!(name.unwrap(), "timestamps");
assert_eq!(value, data);
}
_ => panic!("Expected LongArray tag"),
}
}
}