use std::any::type_name;
#[derive(Clone, Copy)]
pub struct AnyRef {
pointer: Option<*mut u8>,
type_name: &'static str,
}
impl std::fmt::Debug for AnyRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("AnyRef").field(&self.type_name).finish()
}
}
unsafe impl Send for AnyRef {}
unsafe impl Sync for AnyRef {}
impl AnyRef {
pub fn new_zero() -> Self {
AnyRef {
pointer: None,
type_name: "",
}
}
pub fn new<V>(v: &V) -> Self {
let mut res = Self::new_zero();
res.replace(v);
res
}
pub fn is_empty(&self) -> bool {
self.pointer.is_none()
}
pub fn replace<V>(&mut self, v: &V) {
self.check_type::<V>();
self.type_name = type_name::<V>();
let pointer = v as *const V as *mut V as *mut u8;
self.pointer.replace(pointer);
}
#[allow(clippy::mut_from_ref)]
pub fn to_mut<V>(&self) -> &mut V {
self.check_type::<V>();
self.check_none();
unsafe { &mut *(self.pointer.unwrap() as *const V as *mut V) }
}
pub fn to_ref<V>(&self) -> &V {
self.check_type::<V>();
self.check_none();
unsafe { &*(self.pointer.unwrap() as *const V as *mut V) }
}
pub fn get_string(&self) -> String {
self.to_ref::<String>().to_string()
}
fn check_type<V>(&self) {
if self.type_name.is_empty() {
return;
}
let type_name = type_name::<V>();
if type_name != self.type_name {
panic!("类型不一致,期望:{},实际:{}", type_name, self.type_name);
}
}
fn check_none(&self) {
if self.pointer.is_none() {
panic!("数据为空:{}", self.type_name);
}
}
}
#[cfg(test)]
mod tests {
use crate::any::r#ref::AnyRef;
#[test]
fn test() {
assert_eq!(*AnyRef::new(&1).to_ref::<i32>(), 1);
assert_eq!(*AnyRef::new(&"2").to_mut::<&str>(), "2");
assert_ne!(*AnyRef::new(&1).to_ref::<i32>(), 2);
assert_ne!(*AnyRef::new(&"1").to_mut::<&str>(), "2");
}
}