Skip to main content

altv_internal_core_resource/base_objects/base_impl/
mvalue.rs

1use std::ptr::NonNull;
2
3use serde::{de, ser};
4
5use super::{super::AnyBaseObject, base_ptr::BasePtr, BaseObjectContainer};
6use crate::resource::Resource;
7
8// see `serialize_u64` method in mvalue/src/ser_base_object.rs
9impl<T, InheritPtrs: Clone> ser::Serialize for BaseObjectContainer<T, InheritPtrs> {
10  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11  where
12    S: ser::Serializer,
13  {
14    // here its defaults to null ptr because i don't know how to return custom error here.
15    // if ptr is null, mvalue implementation will return InvalidBaseObject error
16    let raw_ptr = self.raw_base_ptr().unwrap_or(std::ptr::null_mut());
17
18    serializer.serialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, &(raw_ptr as u64))
19  }
20}
21
22struct BaseObjectVisitor;
23
24impl<'de> de::Visitor<'de> for BaseObjectVisitor {
25  type Value = AnyBaseObject;
26
27  fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
28    write!(formatter, "Base Object MValue")
29  }
30
31  fn visit_u64<E>(self, base_object_ptr: u64) -> Result<Self::Value, E>
32  where
33    E: de::Error,
34  {
35    let Some(ptr) = NonNull::new(base_object_ptr as altv_sdk::BaseObjectRawMutPtr) else {
36      return Err(E::custom(
37        "Base object is invalid (it has probably already been destroyed)",
38      ));
39    };
40
41    let Some(base_object) = Resource::with_base_objects_ref(|v, _| v.get_by_ptr(ptr)) else {
42      return Err(E::custom(
43        "Base object is not found in the pool (it has probably already been destroyed)",
44      ));
45    };
46
47    Ok(base_object)
48  }
49}
50
51impl<'de> de::Deserialize<'de> for AnyBaseObject {
52  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53  where
54    D: de::Deserializer<'de>,
55  {
56    deserializer.deserialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, BaseObjectVisitor)
57  }
58}
59
60#[macro_export]
61macro_rules! __impl_mvalue_deserialize_for_base_object {
62  ($container:ty, $class_name:ident, $module_name:ident) => {
63    mod $module_name {
64      use serde::{de};
65      use std::ptr::NonNull;
66      use super::*;
67      use $crate::resource::Resource;
68
69      struct BaseObjectVisitor;
70
71      impl<'de> de::Visitor<'de> for BaseObjectVisitor {
72        type Value = $container;
73
74        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
75          write!(formatter, "{} MValue", stringify!($class_name))
76        }
77
78        fn visit_u64<E>(self, base_object_ptr: u64) -> Result<Self::Value, E>
79        where
80          E: de::Error,
81        {
82          let Some(ptr) = NonNull::new(base_object_ptr as altv_sdk::BaseObjectRawMutPtr) else {
83            return Err(E::custom(format!(
84              "{} is invalid (it has probably already been destroyed)",
85              stringify!($class_name)
86            )));
87          };
88
89          let Some(base_object) = Resource::with_base_objects_ref(|v, _| v.get_by_ptr(ptr)) else {
90            return Err(E::custom(format!(
91              "{} is not found in the pool (it has probably already been destroyed)",
92              stringify!($class_name)
93            )));
94          };
95
96          match base_object {
97            AnyBaseObject::$class_name(v) => Ok(v),
98            _ => Err(E::custom(format!(
99              "This base object is not {}",
100              stringify!($class_name)
101            ))),
102          }
103        }
104      }
105
106      impl<'de> de::Deserialize<'de> for $container {
107        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108        where
109          D: de::Deserializer<'de>,
110        {
111          deserializer.deserialize_newtype_struct(mvalue::BASE_OBJECT_MVALUE, BaseObjectVisitor)
112        }
113      }
114    }
115  };
116}
117
118pub use __impl_mvalue_deserialize_for_base_object as impl_deserialize_for;