Vec, Option, and ownership

Apologies I am having a hard time getting this to work in Rust playground. Consider the following:

struct Foo<T> {
        bar: Vec<T>
}

Now in our product we have realized we do not need a vector since we will only ever have 1 of something at most. So we switch to option:

struct Foo<T> {
        bar: Option<T>
}

In most places in our code this change is Completely fine. However we run into issues when T is Request<Body> (http::Request, http::Body). We had no issues before doing Foo.bar[0] to access data and change data on &mut Foo. Now if I do Foo.bar.unwrap() I get:

move occurs because `request` has type `http::Request<Body>`, which does not implement the Copy trait

Request<Body> does not support Copy or Clone.

Why is does Vec work for us but not Option? How do I make option work?

Index (of Vec) takes and produces references while unwrap uses value.
Lazy solution is to call .as_ref() before unwrap, but it it better to not write unwrap() and so handle the case where it is none, without the program panicking.

1 Like

To add some illustration:

    fn quz(&mut self) {
        let _: &mut T = self.bar.as_mut().unwrap();
        let _: &mut T = match self.bar.as_mut() {
            None => return,
            Some(thing) => thing,
        };
    }

(.as_mut() is the mutable version of .as_ref().)

1 Like

So the code is more like this:

fn something(&mut foo: Foo) {
    let request = foo.bar[0];

    match client.request(request) {
     ...
    }

    foo.somthing_else = "value";
}

This all works fine unless I try to use an option, and it gets messy because client.request (in http) is like so:

    pub fn request(&self, mut req: Request<B>) -> ResponseFuture {
        let is_http_connect = req.method() == Method::CONNECT;
        match req.version() {
            Version::HTTP_11 => (),
            Version::HTTP_10 => {
fn something(&mut foo: Foo) {
    let request = foo.bar.as_mut().unwrap();

    match client.request(request) {
     ...
    }

    foo.somthing_else = "value";
}

This doesn't work because request type doesn't match and I can deref request because no Copy trait.

I apologize, on second glance in this case it is .pop and not [0]. Does pop do something different?

It looks like pop has a ptr read:

Perhaps I want to use take?

1 Like

Pop removes the last element so it can actually move it out of the vector, which indexing of course can't do.

1 Like

Maybe you're looking for Option::take?

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.