use std::{borrow::Cow, collections::HashMap};
#[cfg(feature = "serde")]
use std::{fmt, marker::PhantomData};
#[cfg(feature = "entities")]
#[macro_use]
mod macros;
#[cfg(feature = "entities")]
pub(crate) mod list;
pub trait Entity: Clone {}
#[derive(Debug, Clone, PartialEq)]
pub struct GenericEntity {
pub id: Cow<'static, str>,
pub uuid: u128,
pub properties: HashMap<Cow<'static, str>, fastnbt::Value>,
}
impl Entity for GenericEntity {}
impl Entity for fastnbt::Value {}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for GenericEntity {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct _Visitor<'de> {
marker: PhantomData<GenericEntity>,
lifetime: PhantomData<&'de ()>,
}
impl<'de> serde::de::Visitor<'de> for _Visitor<'de> {
type Value = GenericEntity;
fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("Entity")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut id = None;
let mut uuid = None;
let mut properties = HashMap::new();
while let Some(key) = map.next_key::<Cow<'static, str>>()? {
match key.as_ref() {
"id" => {
if id.is_some() {
return Err(serde::de::Error::duplicate_field("id"));
}
id = Some(map.next_value()?);
}
"UUID" => {
if uuid.is_some() {
return Err(serde::de::Error::duplicate_field("UUID"));
}
uuid = Some(map.next_value()?);
}
_ => {
properties.insert(key, map.next_value()?);
}
}
}
let id = id.ok_or_else(|| serde::de::Error::missing_field("id"))?;
let uuid = uuid.ok_or_else(|| serde::de::Error::missing_field("UUID"))?;
Ok(Self::Value {
id,
uuid,
properties,
})
}
}
deserializer.deserialize_map(_Visitor {
marker: PhantomData::<GenericEntity>,
lifetime: PhantomData,
})
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for GenericEntity {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeMap;
let mut state = serializer.serialize_map(Some(self.properties.len() + 2))?;
state.serialize_entry("id", &self.id)?;
state.serialize_entry("UUID", &self.uuid)?;
for (key, value) in &self.properties {
state.serialize_entry(key, value)?;
}
state.end()
}
}