Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind variable to literal in Rust pattern matching

I have a state machine written in Rust which needs to perform the same action for two states.

Both states are variants of an enum but contain a different number of elements.

match self.state {
    RunState::ACCUMULATE(byte, count) | RunState::ESCAPE(count) => todo!(), 
    _ => todo!()
}

The example is invalid source code because byte is not bound in all patterns.

This could be solved by binding byte to a literal zero in the second pattern but i don't know how to archive that.

I`am currently matching both patterns separately which leads to code duplication which i would like to avoid.

Thank you for your attention.

like image 572
Deric Avatar asked Dec 31 '25 17:12

Deric


2 Answers

Patterns are designed to match by structure and bind variables based on the value being matched. It is not designed to introduce arbitrary bindings. You should use separate match arms and perhaps use a helper function if you're concerned about duplication:

match self.state {
    RunState::ACCUMULATE(byte, count) => helper(byte, count),
    RunState::ESCAPE(count) => helper(0, count), 
    ...
}

Or you can introduce a function for your enum that returns the needed values like:

impl RunState {
    fn to_parts(&self) -> (u8, usize) { // or Option<(u8, usize)> if its not applicable to all
        match self.state {
            RunState::ACCUMULATE(byte, count) => (byte, count),
            RunState::ESCAPE(count) => (0, count), 
            ...
        }
    }
}
like image 170
kmdreko Avatar answered Jan 02 '26 05:01

kmdreko


You can solve your issue by not binding byte in any branch:

match self.state {
    RunState::ACCUMULATE(_, count) | RunState::ESCAPE(count) => todo!(), 
    _ => todo!()
}

If you need byte in the ACCUMULATE case, then the code isn't strictly speaking the same for both, but this can be accomplished with an extra step to extract byte:

match self.state {
    RunState::ACCUMULATE(_, count) | RunState::ESCAPE(count) => {
        let byte = if let RunState::ACCUMULATE (byte, _) = self.state { byte } else { 0 };
        todo!()
    }, 
    _ => todo!()
}
like image 37
Jmb Avatar answered Jan 02 '26 07:01

Jmb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!