-1
pub fn get_latest_packet(&mut self) -> Option<Packet> {   
     let packet = self.to_send.lock().unwrap().pop_front();
     packet
}

where pub to_send: Arc<Mutex<VecDeque<Packet>>>,

I'm trying to do this:

let packet = smol_socket.get_latest_packet();
match packet {
    Some(packet) => {
         packet.blob.start = 0;

I'm getting that I can't because packet is not mutable. I can't simply do let mut packet = ... because this would make the Option mutable, not the packet. Is there a way to match packet with it being mutable?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Guerlando OCs
  • 1,886
  • 9
  • 61
  • 150
  • Try `match &mut packet {` – Lambda Fairy Jun 30 '20 at 04:01
  • It looks like your question might be answered by the answers of [Calling a method on a value inside a mutable Option](https://stackoverflow.com/q/27361350/155423); [How do I borrow a reference to what is inside an Option?](https://stackoverflow.com/q/22282117/155423). If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jun 30 '20 at 12:57

2 Answers2

2

There are many ways that work for modifying a value inside a match. It seems there are quite a few subtleties. Here we've collected a variety of solutions

All the examples are based on the following common code

#[derive(Debug)]
pub struct Packet {
    blob_start:u32
}

pub fn get_latest_packet() -> Option<Packet> {
    Some(Packet{ blob_start:10 })
}

main() {
  let mut packet = get_latest_packet();
  println!("packet = {}", packet);
  // ... match goes here ...
  println!("packet = {}", packet);
}

Matching on a mutable reference with mut ref arms.

This was my original version

    match &mut packet {
        Some(ref mut packet) => { packet.blob_start = 0; }
        None => { }
    }

playground

It was pointed out that this only works due to match egronomics, and is equivalent to:

    match &mut packet {
        &mut Some(ref mut packet) => { packet.blob_start = 0; }
        &mut None => { }
    }

playground

Matching by value with a mut ref arm

You don't need to pass a reference - you can just pass the value, and so long as you take a mutable reference to the contained packet object it works.

match packet {
    Some(ref mut packet) => { packet.blob_start = 0; }
    None => { }
}

playground

Matching with on mutable reference, with default arms

match &mut packet {
    Some(packet) => { packet.blob_start = 0; }
    None => { }
}

playground

Again this seems to rely on the match ergonomics details.

Matching by value with mut arm.

If you don't need to access the packet option after the match you can use this:

match packet {
    Some(mut packet) => {
        packet.blob.start = 0;
        // ... do something with the packet ...
    }
}

In this case, you don't need the mut on the packet option either. playground

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
-1

What you almost certainly want is simply something along the lines of:

packet.map(|inner| {
    inner.blob.start = 0;
    inner
});

Using Option::map. In this case, the function that is passed the value that be contained in the Option owns the value, and as such is free to do with it as it pleases.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Zorf
  • 6,334
  • 2
  • 29
  • 24
  • But packet is not iterateable, it's cimply a stuct that holds a blob, which is a simple struct also – Guerlando OCs Jun 30 '20 at 03:21
  • Zorf means `let packet = smol_socket.get_latest_packet().map(|inner|{inner.blob.start = 0; inner})` I think. You're mapping the `Option` not the `Packet`. – Michael Anderson Jun 30 '20 at 03:54
  • @MichaelAnderson oh ok. But actually I was making a simplification of the problem. I actually need to check somethings inside the packet before to then set the start – Guerlando OCs Jun 30 '20 at 03:57