From 9d495ba2392ede584152befb86094c67c6e7bf9a Mon Sep 17 00:00:00 2001 From: Spectre Date: Mon, 19 May 2025 13:51:49 +0200 Subject: [PATCH] starting --- .gitignore | 6 ++- Cargo.lock | 7 +++ Cargo.toml | 6 +++ src/lib.rs | 136 ++++++++++++++++++++++++++++++++++++++++++++++ src/test.rs | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/test.rs diff --git a/.gitignore b/.gitignore index 0104787..423b479 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,8 @@ target/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # 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. -#.idea/ \ No newline at end of file +#.idea/ + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..140aa01 --- /dev/null +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a81a699 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "nbt" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..13c9016 --- /dev/null +++ b/src/lib.rs @@ -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, + value: i8, + }, + Short { + name: Option, + value: i16, + }, + Int { + name: Option, + value: i32, + }, + Long { + name: Option, + value: i64, + }, + Float { + name: Option, + value: f32, + }, + Double { + name: Option, + value: f64, + }, + ByteArray { + name: Option, + value: Vec, + }, + String { + name: Option, + value: String, + }, + List { + name: Option, + element_id: TagId, + elements: Vec, + }, + Compound { + name: Option, + entries: HashMap, + }, + IntArray { + name: Option, + value: Vec, + }, + LongArray { + name: Option, + value: Vec, + }, +} + +impl Tag { + pub fn new_byte(name: impl Into, v: i8) -> Tag { + Tag::Byte { + name: Some(name.into()), + value: v, + } + } + pub fn new_short(name: impl Into, v: i16) -> Tag { + Tag::Short { + name: Some(name.into()), + value: v, + } + } + pub fn new_int(name: impl Into, v: i32) -> Tag { + Tag::Int { + name: Some(name.into()), + value: v, + } + } + pub fn new_long(name: impl Into, v: i64) -> Tag { + Tag::Long { + name: Some(name.into()), + value: v, + } + } + pub fn new_float(name: impl Into, v: f32) -> Tag { + Tag::Float { + name: Some(name.into()), + value: v, + } + } + pub fn new_double(name: impl Into, v: f64) -> Tag { + Tag::Double { + name: Some(name.into()), + value: v, + } + } + pub fn new_ByteArray(name: impl Into, v: Vec) -> Tag { + Tag::ByteArray { + name: Some(name.into()), + value: v, + } + } + pub fn new_string(name: impl Into, v: impl Into) -> Tag { + Tag::String { + name: Some(name.into()), + value: v.into(), + } + } + pub fn new_list(name: impl Into, element_id: TagId, elements: Vec) -> Tag { + Tag::List { + name: Some(name.into()), + element_id, + elements, + } + } + pub fn new_compound(name: impl Into) -> Tag { + Tag::Compound { + name: Some(name.into()), + entries: HashMap::new(), + } + } + pub fn new_int_array(name: impl Into, v: Vec) -> Tag { + Tag::IntArray { + name: Some(name.into()), + value: v, + } + } + pub fn new_long_array(name: impl Into, v: Vec) -> Tag { + Tag::LongArray { + name: Some(name.into()), + value: v, + } + } +} + diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..4dfd8f6 --- /dev/null +++ b/src/test.rs @@ -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"), + } + } +}