lang-extension 1.3.0

Rust Lang Extension
Documentation
use std::any::{Any, type_name};

#[macro_use]
mod as_macro;

#[macro_use]
mod value;
pub use value::*;

#[macro_use]
mod key;
pub use key::*;

mod immutable;
pub use immutable::*;

pub trait AsAny: Any {
    fn as_any_ref(&self) -> &dyn Any;

    fn as_any_mut(&mut self) -> &mut dyn Any;
}

impl<T: Any> AsAny for T {
    fn as_any_ref(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

pub trait AnyExtension {
    fn type_name(&self) -> &'static str {
        type_name::<Self>()
    }
    fn memory_address(&self) -> usize {
        self as *const Self as *const () as usize
    }
    fn reference_equals(&self, other: &dyn Any) -> bool {
        self.memory_address() == other.memory_address()
    }
}

impl<T: ?Sized> AnyExtension for T {}

#[cfg(test)]
mod tests {
    use super::*;
    use std::any::TypeId;

    #[test]
    fn as_any() {
        let d = 1;
        d.type_id();
        assert_eq!(d.as_any_ref().type_id(), TypeId::of::<i32>());

        let mut d = d;
        *d.as_any_mut().downcast_mut::<i32>().unwrap() = 2;
        assert_eq!(2, d);
    }

    #[test]
    fn any_extension() {
        let a: Box<dyn Any> = Box::new(10);
        println!(
            "type_name: {}, memory_address: {:?}",
            a.as_ref().type_name(),
            a.as_ref().memory_address()
        );

        assert_eq!(type_name::<i32>(), 10.type_name());
        assert_eq!(type_name::<dyn Any>(), a.as_ref().type_name());
        assert_eq!(type_name::<Box<dyn Any>>(), a.type_name());

        assert_eq!(
            a.as_ref().downcast_ref::<i32>().unwrap() as *const i32 as usize,
            a.as_ref().memory_address()
        );
        assert_eq!(
            &a as *const Box::<dyn Any> as *const () as usize,
            a.memory_address()
        );

        let b: Box<dyn Any> = Box::new(10);
        assert!(!a.reference_equals(b.as_any_ref()));

        let x = Box::new(10);
        assert_eq!(x, x);
        assert!(x.reference_equals(x.as_any_ref()));

        let y = Box::new(10);
        assert_eq!(x, y);
        assert!(!x.reference_equals(y.as_any_ref()));
        assert!(!x.as_ref().reference_equals(y.as_ref().as_any_ref()));
    }
}