shipyard 0.6.2

Entity Component System
Documentation
use super::EntityId;
use core::fmt;
use core::num::NonZeroU64;
use serde::{
    de::{self, MapAccess, SeqAccess, Visitor},
    ser::SerializeStruct,
    Deserialize, Deserializer, Serialize, Serializer,
};

const FIELDS: &[&str] = &["index", "gen"];

impl Serialize for EntityId {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if serializer.is_human_readable() {
            let mut ser_struct = serializer.serialize_struct("EntityId", 2)?;
            ser_struct.serialize_field(FIELDS[0], &(self.index()))?;
            ser_struct.serialize_field(FIELDS[1], &(self.gen()))?;
            ser_struct.end()
        } else {
            let clone = self.clone();
            ((clone.0).get() - 1).serialize(serializer)
        }
    }
}

impl<'de> Deserialize<'de> for EntityId {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        enum Field {
            Index,
            Generation,
        }

        impl<'de> Deserialize<'de> for Field {
            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
            where
                D: Deserializer<'de>,
            {
                struct FieldVisitor;

                impl<'de> Visitor<'de> for FieldVisitor {
                    type Value = Field;

                    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                        formatter.write_str("`index` or `gen`")
                    }

                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
                    where
                        E: de::Error,
                    {
                        match value {
                            "index" => Ok(Field::Index),
                            "gen" => Ok(Field::Generation),
                            _ => Err(de::Error::unknown_field(value, FIELDS)),
                        }
                    }
                }

                deserializer.deserialize_identifier(FieldVisitor)
            }
        }

        struct EntityIdVisitor;

        impl<'de> Visitor<'de> for EntityIdVisitor {
            type Value = EntityId;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("struct EntityId")
            }

            fn visit_seq<V>(self, mut seq: V) -> Result<EntityId, V::Error>
            where
                V: SeqAccess<'de>,
            {
                let index = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;

                let generation = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;

                Ok(EntityId::new_from_parts(index, generation))
            }

            fn visit_map<V>(self, mut map: V) -> Result<EntityId, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut index = None;
                let mut generation = None;

                while let Some(key) = map.next_key()? {
                    match key {
                        Field::Index => {
                            if index.is_some() {
                                return Err(de::Error::duplicate_field("index"));
                            }
                            index = Some(map.next_value()?);
                        }
                        Field::Generation => {
                            if generation.is_some() {
                                return Err(de::Error::duplicate_field("gen"));
                            }
                            generation = Some(map.next_value()?);
                        }
                    }
                }

                let index = index.ok_or_else(|| de::Error::missing_field("index"))?;
                let generation = generation.ok_or_else(|| de::Error::missing_field("gen"))?;

                Ok(EntityId::new_from_parts(index, generation))
            }
        }

        if deserializer.is_human_readable() {
            deserializer.deserialize_struct("EntityId", FIELDS, EntityIdVisitor)
        } else {
            let non_zero: u64 = Deserialize::deserialize(deserializer)?;

            Ok(EntityId(unsafe { NonZeroU64::new_unchecked(non_zero + 1) }))
        }
    }
}

#[test]
fn serde_json() {
    let string = serde_json::to_string(&EntityId::new_from_index_and_gen(10, 2)).unwrap();
    assert_eq!(r#"{"index":10,"gen":2}"#, string);

    let entity = serde_json::de::from_str::<EntityId>(&string).unwrap();
    assert_eq!(entity, EntityId::new_from_index_and_gen(10, 2));
}

#[test]
fn bincode() {
    let bytes = bincode::serialize(&EntityId::new_from_parts(10, 2)).unwrap();
    assert_eq!(&[10, 0, 0, 0, 0, 0, 2, 0][..], &bytes);

    let entity = bincode::deserialize::<EntityId>(&bytes).unwrap();
    assert_eq!(entity, EntityId::new_from_parts(10, 2));
}