Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Possible to avoid cloning when returning the same option twice?

I have a rather weird case where I need to return a option of a vec, both inside a struct, and just as as the option.
I made a small example here, which looks silly, but it’s the same issue I have in a setting where it makes more sense (in the real world, the container represents a state to compute a next function, while the output option is a output to the user of my api)

pub struct Container {
    opt : Option<Vec<u8>>
}
pub fn return_option(plaintext: Vec<u8>) -> Option<Vec<u8>> {
    match plaintext.len() {
        l if l > 5 => None,
        _ => Some(plaintext)
    }
    
}

pub fn return_stuff(plaintext: Vec<u8>) -> (Container,Option<Vec<u8>>) {

    let dummycontainer = return_option(plaintext);

    return (Container{
        opt : dummycontainer.clone(),
    },
    dummycontainer)
    
}

So, the return_stuff, is the important one, in order not to have the compiler complain about the dummycontainer being a moved value.

In order to get around this, I clone the option, which sounds like an antipattern to me.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there any way around doing this, while still passing the options two different places?

EDIT

borrowing with a static lifetime seems to be the best route.
I just have no idea how. Trying to write the struct like this:

pub struct Container {
    opt : Option<&'a [u8]>
}

Is not allowed, and neither is:

pub fn return_stuff(plaintext: Vec<u8>) -> (Container,Option<&'a [u8]>) {

>Solution :

Assuming someone else owns the Vec<u8> and everything you’re talking about is strictly read-only, we can do the entire thing with slices. The original value can still be a Vec<u8>, but we’re never passing ownership of that to any of the functions mentioned here.

pub struct Container<'a> {
  opt : Option<&'a [u8]>
}

pub fn return_option<'a>(plaintext: &'a [u8]) -> Option<&'a [u8]> {
  match plaintext.len() {
    l if l > 5 => None,
    _ => Some(plaintext)
  }
}

pub fn return_stuff<'a>(plaintext: &'a [u8]) -> (Container<'a>,Option<&'a [u8]>) {
  let dummycontainer = return_option(plaintext);
  return (
    Container{
      opt: dummycontainer,
    },
    dummycontainer,
  )
}

If you’ve got a vector my_vec, you call these functions by borrowing it, as return_stuff(&my_vec[..]).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading