From 05615c365f40173d9c4373c5eb3277dd673f907d Mon Sep 17 00:00:00 2001 From: maxomatic458 <104733404+maxomatic458@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:58:43 +0200 Subject: [PATCH 1/3] (de)serialize for ``ItemStack`` and ``ItemKind`` --- crates/valence_generated/Cargo.toml | 1 + crates/valence_generated/build/item.rs | 24 ++++++++++++++++++++++++ crates/valence_protocol/src/item.rs | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/valence_generated/Cargo.toml b/crates/valence_generated/Cargo.toml index 3cc9f4a4e..0c13460ab 100644 --- a/crates/valence_generated/Cargo.toml +++ b/crates/valence_generated/Cargo.toml @@ -16,6 +16,7 @@ workspace = true valence_math.workspace = true valence_ident.workspace = true uuid.workspace = true +serde = { workspace = true, features = ["derive"] } [build-dependencies] anyhow.workspace = true diff --git a/crates/valence_generated/build/item.rs b/crates/valence_generated/build/item.rs index 248212982..89a39d34b 100644 --- a/crates/valence_generated/build/item.rs +++ b/crates/valence_generated/build/item.rs @@ -173,6 +173,9 @@ pub(crate) fn build() -> anyhow::Result { .collect::(); Ok(quote! { + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use serde::de::{self, Unexpected}; + /// Represents an item from the game #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] #[repr(u16)] @@ -193,6 +196,27 @@ pub(crate) fn build() -> anyhow::Result { pub snack: bool, } + impl Serialize for ItemKind { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.to_str()) + } + } + + impl<'de> Deserialize<'de> for ItemKind { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: &str = Deserialize::deserialize(deserializer)?; + ItemKind::from_str(s).ok_or_else(|| { + de::Error::invalid_value(Unexpected::Str(s), &"the snake case item name, like \"white_wool\"") + }) + } + } + impl ItemKind { /// Constructs a item kind from a raw item ID. /// diff --git a/crates/valence_protocol/src/item.rs b/crates/valence_protocol/src/item.rs index 057ea632d..0cb6fd415 100644 --- a/crates/valence_protocol/src/item.rs +++ b/crates/valence_protocol/src/item.rs @@ -1,12 +1,13 @@ use std::io::Write; +use serde::{Deserialize, Serialize}; pub use valence_generated::item::ItemKind; use valence_nbt::Compound; use crate::{Decode, Encode}; /// A stack of items in an inventory. -#[derive(Clone, PartialEq, Debug, Default)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)] pub struct ItemStack { pub item: ItemKind, pub count: i8, From 627f540f4ba6f83c657b6d78df657f9a8ce0d2e0 Mon Sep 17 00:00:00 2001 From: maxomatic458 <104733404+maxomatic458@users.noreply.github.com> Date: Sat, 12 Oct 2024 11:08:00 +0200 Subject: [PATCH 2/3] remove ``use serde`` in macro --- crates/valence_generated/build/item.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/valence_generated/build/item.rs b/crates/valence_generated/build/item.rs index 89a39d34b..74e670cf7 100644 --- a/crates/valence_generated/build/item.rs +++ b/crates/valence_generated/build/item.rs @@ -173,9 +173,6 @@ pub(crate) fn build() -> anyhow::Result { .collect::(); Ok(quote! { - use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use serde::de::{self, Unexpected}; - /// Represents an item from the game #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] #[repr(u16)] @@ -196,23 +193,23 @@ pub(crate) fn build() -> anyhow::Result { pub snack: bool, } - impl Serialize for ItemKind { + impl serde::Serialize for ItemKind { fn serialize(&self, serializer: S) -> Result where - S: Serializer, + S: serde::Serializer, { serializer.serialize_str(self.to_str()) } } - impl<'de> Deserialize<'de> for ItemKind { + impl<'de> serde::Deserialize<'de> for ItemKind { fn deserialize(deserializer: D) -> Result where - D: Deserializer<'de>, + D: serde::Deserializer<'de>, { - let s: &str = Deserialize::deserialize(deserializer)?; + let s: &str = serde::Deserialize::deserialize(deserializer)?; ItemKind::from_str(s).ok_or_else(|| { - de::Error::invalid_value(Unexpected::Str(s), &"the snake case item name, like \"white_wool\"") + serde::de::Error::invalid_value(serde::de::Unexpected::Str(s), &"the snake case item name, like \"white_wool\"") }) } } From 2baa43513288493f4c4bbbd5089b7ab309bd0e5d Mon Sep 17 00:00:00 2001 From: maxomatic458 <104733404+maxomatic458@users.noreply.github.com> Date: Sat, 12 Oct 2024 23:50:51 +0200 Subject: [PATCH 3/3] add tests for serialization --- Cargo.toml | 1 + src/tests.rs | 1 + src/tests/serialization.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/tests/serialization.rs diff --git a/Cargo.toml b/Cargo.toml index 1371871b4..c0da23ef0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,7 @@ divan.workspace = true flume.workspace = true noise.workspace = true # For the terrain example. tracing.workspace = true +serde_json.workspace = true # For serialization tests. [dev-dependencies.reqwest] workspace = true diff --git a/src/tests.rs b/src/tests.rs index e82971210..0693a4497 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -7,5 +7,6 @@ mod layer; mod player_list; mod potions; mod scoreboard; +mod serialization; mod weather; mod world_border; diff --git a/src/tests/serialization.rs b/src/tests/serialization.rs new file mode 100644 index 000000000..986a1e178 --- /dev/null +++ b/src/tests/serialization.rs @@ -0,0 +1,35 @@ +use crate::ItemKind; + +#[test] +fn test_serialize_item_kind() { + let item = ItemKind::WhiteWool; + let serialized = serde_json::to_string(&item).unwrap(); + assert_eq!(serialized, "\"white_wool\""); + + let item = ItemKind::GoldenSword; + let serialized = serde_json::to_string(&item).unwrap(); + assert_eq!(serialized, "\"golden_sword\""); + + let item = ItemKind::NetheriteAxe; + let serialized = serde_json::to_string(&item).unwrap(); + assert_eq!(serialized, "\"netherite_axe\""); + + let item = ItemKind::WaxedWeatheredCutCopperStairs; + let serialized = serde_json::to_string(&item).unwrap(); + assert_eq!(serialized, "\"waxed_weathered_cut_copper_stairs\""); +} + +#[test] +fn test_deserialize_item_kind() { + let id = "\"diamond_shovel\""; + let deserialized: ItemKind = serde_json::from_str(id).unwrap(); + assert_eq!(deserialized, ItemKind::DiamondShovel); + + let id = "\"minecart\""; + let deserialized: ItemKind = serde_json::from_str(id).unwrap(); + assert_eq!(deserialized, ItemKind::Minecart); + + let id = "\"vindicator_spawn_egg\""; + let deserialized: ItemKind = serde_json::from_str(id).unwrap(); + assert_eq!(deserialized, ItemKind::VindicatorSpawnEgg); +}