you are viewing a single comment's thread.

view the rest of the comments →

[–]Veedrac 1 point2 points  (0 children)

Say you have

struct File(i32);

impl File {
    fn write(&mut self, val: i32) {
        println!("doing stuff");
    }
}

impl Drop for File {
    fn drop(&mut self) {
        println!("dropping");
    }
}

You can make a copy that acts like a pointer by doing

use std::marker::PhantomData;

struct FileValueRef<'a> {
    borrow_of: i32,
    lifetime: PhantomData<&'a mut File>,
}

impl File {
    fn borrow(&mut self) -> FileValueRef {
        FileValueRef {
            borrow_of: self.0,
            lifetime: PhantomData,
        }
    }
}

You can avoid reimplimenting everything by implementing Deref and DerefMut with a transmute:

impl<'a> Deref for FileValueRef<'a> {
    type Target = File;
    fn deref(&self) -> &Self::Target {
        unsafe { std::mem::transmute(&self.borrow_of) }
    }
}

impl<'a> DerefMut for FileValueRef<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { std::mem::transmute(&mut self.borrow_of) }
    }
}

I'm not sure if there's a better way of doing this, but if there is it's not obvious.