Move value out of enum

Let's say I have something like this:

enum State<R> {
  Waiting,
  Aborted,
  Message(R)
}

An instance of this is placed behind a mutex Arc<Mutex<State<R>>>.

I have a function that returns a Result<R, Error>. There are the following situations to consider:

  • If it's State::Message(R), return Ok(R)
  • If it's State::Aborted, return Err()
  • State::Waiting means the function will loop.

Is it possible to move the value out of the enum in some way so that I can return it? The value in the Arc<Mutex<>> obviously needs a value, but is it possible to replace it with another (dummy) enum value and take the Message(R) value out?

And let's say that there's a way to switch out a State::Message(R) with a State::Waiting (it would be ok to do this at this state), is there then a way to move the R out of the State::Message(R)?

(I'm specifically asking how to solve this with moves; i.e. I don't want to introduce any Clone trait bounds).

Sure.

fn take_the_message<R>(container: &Mutex<State<R>>) -> R {
    let mut lock = container.lock().unwrap();
    let msg = std::mem::replace(&mut *lock, State::Waiting);
    match msg {
        State::Message(msg) => msg,
        _ => panic!("Not State::Message"),
    }
}

playground

3 Likes