objt 0.1.0

Reference counted object helpers
Documentation
#[macro_export]
macro_rules! objt {
    ($name:ident, $weakname:ident, $inner:ident, $($member:ident: $member_type:ty),* ) => {
        #[derive(Clone)]
        pub struct $name(std::rc::Rc<std::cell::RefCell<$inner>>);

        pub struct $weakname(std::rc::Weak<std::cell::RefCell<$inner>>);

        impl $name {
            pub(crate) fn from_inner(inner: $inner) -> Self {
                $name(std::rc::Rc::new(std::cell::RefCell::new(inner)))
            }

            #[track_caller]
            pub(crate) fn borrow(&self) -> std::cell::Ref<$inner> {
                // let caller_location = std::panic::Location::caller();
                // tracing::debug!("borrowing {}, at {}:{}", stringify!($name), caller_location.file(), caller_location.line());
                (*self.0).borrow()
            }

            #[track_caller]
            pub(crate) fn borrow_mut(&self) -> std::cell::RefMut<$inner> {
                // let caller_location = std::panic::Location::caller();
                // tracing::debug!("borrowing mut {}, at {}:{}", stringify!($name), caller_location.file(), caller_location.line());
                (*self.0).borrow_mut()
            }

            pub fn clone_ref(&self) -> Self {
                $name(self.0.clone())
            }

            $(pub(crate) fn $member(&self) -> $member_type {
                self.borrow().$member.clone()
            })*

            pub fn as_weak(&self) -> $weakname {
                $weakname(std::rc::Rc::downgrade(&self.0))
            }

            pub fn in_future<F: futures::Future, FC: FnOnce($name) -> F>(&self, f: FC) -> F {
                f(self.clone_ref())
            }
        }

        impl $weakname {
            pub(crate) fn upgrade(&self) -> Option<$name> {
                self.0.upgrade().map($name)
            }
        }
    };
}

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

    #[test]
    fn it_works() {
        pub struct TestInner {
            a: u32,
            b: u32,
        }

        objt!(Test, WeakTest, TestInner, a: u32, b: u32);

        let test = Test::from_inner(TestInner { a: 1, b: 2 });
        println!("a: {}, b: {}", test.a(), test.b());
    }
}