use std::ptr::NonNull;
use serde::{de, ser};
use super::{super::AnyBaseObject, base_ptr::BasePtr, BaseObjectContainer};
use crate::resource::Resource;
impl<T, InheritPtrs: Clone> ser::Serialize for BaseObjectContainer<T, InheritPtrs> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let raw_ptr = self.raw_base_ptr().unwrap_or(std::ptr::null_mut());
serializer.serialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, &(raw_ptr as u64))
}
}
struct BaseObjectVisitor;
impl<'de> de::Visitor<'de> for BaseObjectVisitor {
type Value = AnyBaseObject;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "Base Object MValue")
}
fn visit_u64<E>(self, base_object_ptr: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
let Some(ptr) = NonNull::new(base_object_ptr as altv_sdk::BaseObjectRawMutPtr) else {
return Err(E::custom("Base object is invalid (it has probably already been destroyed)"));
};
let Some(base_object) = Resource::with_base_objects_ref(|v, _| v.get_by_ptr(ptr)) else {
return Err(E::custom("Base object is not found in the pool (it has probably already been destroyed)"));
};
Ok(base_object)
}
}
impl<'de> de::Deserialize<'de> for AnyBaseObject {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, BaseObjectVisitor)
}
}
#[macro_export]
macro_rules! __impl_mvalue_deserialize_for_base_object {
($container:ty, $class_name:ident, $module_name:ident) => {
mod $module_name {
use serde::{de};
use std::ptr::NonNull;
use super::*;
use $crate::resource::Resource;
struct BaseObjectVisitor;
impl<'de> de::Visitor<'de> for BaseObjectVisitor {
type Value = $container;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(formatter, "{} MValue", stringify!($class_name))
}
fn visit_u64<E>(self, base_object_ptr: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
let Some(ptr) = NonNull::new(base_object_ptr as altv_sdk::BaseObjectRawMutPtr) else {
return Err(E::custom(format!("{} is invalid (it has probably already been destroyed)", stringify!($class_name))));
};
let Some(base_object) = Resource::with_base_objects_ref(|v, _| v.get_by_ptr(ptr)) else {
return Err(E::custom(format!("{} is not found in the pool (it has probably already been destroyed)", stringify!($class_name))));
};
match base_object {
AnyBaseObject::$class_name(v) => Ok(v),
_ => Err(E::custom(format!("This base object is not {}", stringify!($class_name)))),
}
}
}
impl<'de> de::Deserialize<'de> for $container {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, BaseObjectVisitor)
}
}
}
};
}
pub use __impl_mvalue_deserialize_for_base_object as impl_deserialize_for;