Help with interior mutability

Hey community,

I've finally taken the time to start learning Rust over the past few days. I get absolutely get the fuss over Rust, it's been a liberating experience. I had forgotten how much fun coding used to be. I decided to tackle a problem that is complex enough to pace me through the language, without forcing me to think too much about how to solve the problem itself: a Minecraft server.

The Minecraft protocol negotiates AES CFB8 early in the stream. The natural way to express this in Rust would be with Option<AesCfb8>, but I couldn't get the mutability/reference correct (I tried Box and Cell, both inside and outside the Option). The cipher kept resetting between packets, so my mutable reference was clearly a reference to a copy. To get things working I resorted to this:

pub struct PacketWriter<W: AsyncWrite + Unpin> {
    target: Vec<u8>,
    writer: W,
    encrypted: bool,
    crypt: AesCfb8, // Cfb8<Aes128> from aes and cfb crates
}

Which is used as follows:

// &mut self
if self.encrypted {
    self.crypt.decrypt(&mut self.buffer.space()[0..n]);
}

I feel as though I've missed an opportunity to learn here, by going with the non-idiomatic route. The goal is obviously something along the lines of (which I never committed, so I no longer have a specimen of my failed attempt at idiomatic code):

// &mut self
if let Some(cipher) = &mut self.cipher {
    cipher.decrypt(&mut self.buffer.space()[0..n]);
}

Any tips elsewhere in the repo are obviously more than welcome, but we're all busy people :slight_smile:

You should just need to have cipher: Option<AesCfb8> and:

if let Some(cipher) = self.cipher.as_mut() {
    cipher.decrypt(self.buffer.space()[0..n]);
}

The key method here is Option::as_mut.

1 Like

Thanks a million, that works perfectly!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.