How to change struct member enum's variant to another, moving the value?

50 Views Asked by At

I am trying to implement a state machine for audio playback in Rust. A Playback struct can store a file and whether the playback is playing/paused/stopped, with playing/paused states saving playback position. The code is very simple:

struct PlaybackProgress {
    playback_position: f32,
    stream_id: usize
}


enum PlaybackState {
    Stopped,
    Playing(PlaybackProgress),
    Paused(PlaybackProgress)
}

struct Playback {
    file: Option<String>,
    state: PlaybackState,
}

impl Playback {
    // Creates a new empty Playback instance (no file, stopped)
    pub fn new() -> Self {
        Playback {
            file: None,
            state: PlaybackState::Stopped
        }
    }

    pub fn play(&mut self, file: String) -> bool {
        match &self.state {
            PlaybackState::Playing(_) => {
                false
            }
            PlaybackState::Paused(progress) => {
                self.state = PlaybackState::Playing(progress); // THE ISSUE
                true
            }
            PlaybackState::Stopped => {
                self.file = Some(file);
                self.state = PlaybackState::Playing(PlaybackProgress { 
                    playback_position: 0.0, 
                    stream_id: 1 
                });
                true
            }
        }
    }
}

The issue is changing a Paused variant to a Playing while keeping the same progress. When trying match self.state, the compiler doesn't allow moving progress, and suggests borrowing (i.e. match &self.state), in which case there is a type mismatch between a reference and value.

I am confused why the issue is there, since the moved value would still be owned by parent struct and have the same lifetime as before.

What's a simple readable way to achieve this?

Note: I have read this question and its answers, none of which worked. First answer suggests using an immutable value (impossible since this is a state machine and struct needs to be mutated), or storing a dummy value (impossible, when trying *self.state compiler says it cannot be dereferenced for reasons beyond my understanding). Other questions suggests using unsafe (which I won't do for such a simple task), or Rc<>/Option<>, which don't make sense in this case.

0

There are 0 best solutions below