Method that consumes self - I'm stuck

Hi all.

I'm playing with the crate jack and I'm facing a problem really new to me.
the jack::Client struct Client in jack - Rust
has a method activate_client that consumes self and returns an AsyncClient AsyncClient in jack - Rust . My original Client will be handed back to me when, later, I'll call AsyncClient::deactivate. I don't know if this is relevant to my problem (maybe not).

The provided example that I'm following rust-jack/playback_capture.rs at main · RustAudio/rust-jack · GitHub essentially does everything in one single function: line 7 it creates the Client instance (client variable), line 36 Client gets consumed to produce AsyncClient (active_client variable). After that, the client variable is no longer used. So far, so good.

But in my own code I'm in a different situation: the Client::activate_async funcion is necessarily called separately (in a different function) from Client::new, and the Client instance is kept in a dedicated struct among other things. I summarized my code here in this playground. The error you get compiling this example is the same I get in my application using jack. I hope this is a proper reconstruction of my problem.

As of my understanding, my problem is (relative to my example in the playground) that activate_async can't consume self (that is Client) because Client is still inside VariousThings and, potentially, could be used again. Am I right?

What should I do? How can I get out of here?

Another question: what if jack::Client::activate_async returns Result:Err instead of Result::Ok? Is the consumed Client lost forever?

Thanks for any hint!

You can use Option::take to move out of the client field

Playground

#![allow(dead_code, unused_variables, unused_imports)]

struct AsyncClient;

struct Client;

impl Client {
    
    fn activate_async(self) -> Result<AsyncClient, String> {
        
        let active_client = AsyncClient;
        Ok(active_client)
        
    }
}

struct VariousThings {
    client: Option<Client>
}

impl VariousThings {
    
    fn start(&mut self) {
        
        let active_client = self.client.take().unwrap().activate_async().unwrap();
        
    }
}

fn main() {

    let mut things = VariousThings { client: Some(Client) };
    things.start();

    
}

That means you won't be able to successfully access the client until you store something back to that field though. You may need to store the information necessary to create a new Client if it's possible to recover from some of those errors and you want to do that.

2 Likes

Oh... I should have figure it out by myself...

Thank you!