Which pointer type to choose for an enum method where one variant owns the value and another has an Rc<RefCell> pointing to it?

I have this enum which currently mainly determines the way in which the game client accesses the physics state:

pub enum ClientMode {
    /// In singleplayer mode, the client uses the scene's dynamics directly
    Singleplayer { dynamics: Rc<RefCell<Dynamics>> },
    /// In multiplayer mode, the client has its own dynamics
    Multiplayer { dynamics: Dynamics },
}

// ...

    pub fn get_dynamics_ref(&self) -> &Dynamics

// ...

Other parts of my code have to work with &Dynamics in order to read the positions of objects in the game world.

However this seems impossible: it would be a violation to get a & out of a RefCell because it cannot do dynamic borrow checking that way. Makes sense.

But what other return type can I choose for get_dynamics_ref? One way to easily solve this would be to store it as a Rc in the Multiplayer variant as well: but that seems hacky and otherwise unnecessary--the game client really does own its dynamics struct in that case.

You can just make your own:

pub enum MyRef<'a, T> {
    Borrow(&'a T),
    RefCell(Ref<'a, T>),
}

impl<'a, T> Deref for MyRef<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        match self {
            MyRef::Borrow(r) => r,
            MyRef::RefCell(r) => r.deref(),
        }
    }
}

playground

2 Likes

Would this be a canonical solution in Rust? Seems like a common situation it's weird (to my beginner's eyes) that there's no premade solution

I don't think a solution for this exact problem appears in the standard library. You call it common, but it's the first time I encounter it.

You're probably right. Thank you, it worked!:smiley: