aboutsummaryrefslogtreecommitdiff
path: root/azalea-core/src/codec_utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-core/src/codec_utils.rs')
-rw-r--r--azalea-core/src/codec_utils.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/azalea-core/src/codec_utils.rs b/azalea-core/src/codec_utils.rs
new file mode 100644
index 00000000..0014f86d
--- /dev/null
+++ b/azalea-core/src/codec_utils.rs
@@ -0,0 +1,83 @@
+//! Some functions that are useful to have when implementing
+//! `Serialize`/`Deserialize`, which Azalea uses to imitate Minecraft codecs.
+
+use azalea_buf::SerializableUuid;
+use serde::{Serialize, Serializer, ser::SerializeTupleStruct};
+use uuid::Uuid;
+
+/// Intended to be used for skipping serialization if the value is the default.
+///
+/// ```no_run
+/// #[serde(skip_serializing_if = "is_default")]
+/// ```
+pub fn is_default<T: Default + PartialEq>(t: &T) -> bool {
+ *t == Default::default()
+}
+
+/// Intended to be used for skipping serialization if the value is `true`.
+///
+/// ```no_run
+/// #[serde(skip_serializing_if = "is_true")]
+/// ```
+pub fn is_true(t: &bool) -> bool {
+ *t
+}
+
+/// If the array has a single item, don't serialize as an array
+///
+/// ```no_run
+/// #[serde(serialize_with = "flatten_array")]
+/// ```
+pub fn flatten_array<S: Serializer, T: Serialize>(x: &Vec<T>, s: S) -> Result<S::Ok, S::Error> {
+ if x.len() == 1 {
+ x[0].serialize(s)
+ } else {
+ x.serialize(s)
+ }
+}
+
+/// Minecraft writes UUIDs as an IntArray<4>
+pub fn uuid<'a, S: Serializer>(
+ uuid: impl Into<&'a Option<Uuid>>,
+ serializer: S,
+) -> Result<S::Ok, S::Error> {
+ if let Some(uuid) = uuid.into() {
+ let arr: [u32; 4] = uuid.to_int_array();
+ let arr: [i32; 4] = [arr[0] as i32, arr[1] as i32, arr[2] as i32, arr[3] as i32];
+ IntArray(arr).serialize(serializer)
+ } else {
+ serializer.serialize_unit()
+ }
+}
+
+/// An internal type that makes the i32 array be serialized differently.
+///
+/// Azalea currently only uses this when writing checksums, but Minecraft also
+/// uses this internally when converting types to NBT.
+pub struct IntArray<const N: usize>(pub [i32; N]);
+/// An internal type that makes the i64 array be serialized differently.
+///
+/// Azalea currently only uses this when writing checksums, but Minecraft also
+/// uses this internally when converting types to NBT.
+pub struct LongArray<const N: usize>(pub [i64; N]);
+
+impl<const N: usize> Serialize for IntArray<N> {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ // see checksum::serialize_tuple_struct
+ let mut seq = serializer.serialize_tuple_struct("azalea:int_array", N)?;
+ for &item in &self.0 {
+ seq.serialize_field(&item)?;
+ }
+ seq.end()
+ }
+}
+impl<const N: usize> Serialize for LongArray<N> {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ // see checksum::serialize_tuple_struct
+ let mut seq = serializer.serialize_tuple_struct("azalea:long_array", N)?;
+ for &item in &self.0 {
+ seq.serialize_field(&item)?;
+ }
+ seq.end()
+ }
+}