Loops, moves, and variables

โš“ Rust    ๐Ÿ“… 2026-04-03    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 4      

surdeus

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Loops, moves, and variables

Hello all,

I'm working on the CodeCrafter's Redis project using Rust. I've started on the RESP parser.

I thought it would be interesting to build a parser that receives incrementally the bytes. The question is not so much about the algorithm per se, but using Rust idiomatically.

Here is the full parser: Redis Serialization Protocol ยท GitHub

I've created a type fragment

#[derive(Debug)]
pub enum Fragment {
    Value(RedisValue),
    Array(RedisValue, usize, usize),
}

That basically is an indicator of "Is this Aggregated type complete". RedisValue is just a representing the possible RESP values.

I created this method parse_next that receives bytes and tries to parse a full RedisValue from the bytes that is stored in the result attribute of the Parser struct

When ever I parse a RedisValue I check that if we have a "Fragment" of an Array in the stack (now that I'm writing this what a bad name...) if we do, that RedisValue goes into the Array. If you go an array in an array you have to check that if you completed the array on top of the stack and assign it to the value right before the top... I did this with a loop:

                let mut value_ = &mut value;
                let mut i = 0;
                loop {
                    match self.stack.pop() {
                        Some(Fragment::Value(value)) => {
                            let _ = std::mem::replace(value_, value);
                        }

                        Some(Fragment::Array(RedisValue::Array(mut values), size, current)) => {
                            let tmp = RedisValue::Null;
                            values.push(std::mem::replace(value_, tmp));
                            let current = current + 1;
                            if size <= current {
                                let _ = std::mem::replace(value_, RedisValue::Array(values));
                            } else if size > current {
                                self.stack.push(Fragment::Array(
                                    RedisValue::Array(values),
                                    size,
                                    current,
                                ));
                                break;
                            }
                        }
                        None => {
                            let tmp = RedisValue::Null;
                            self.result = Some(std::mem::replace(value_, tmp));
                            break;
                        }
                        Some(Fragment::Array(_, _, _)) => unreachable!(),
                    }
                }

Question:

  1. Because I move everything. As you can see there are no references I need to have this variable outside the loop and use replace. Is this a thing? What would be a better way to do this? Have box?
  2. I understand that matching Enums should be cheap, so recreating this values shouldn't be too much of an issue, it feels functional programming... Is this ok?

3 posts - 2 participants

Read full topic

๐Ÿท๏ธ Rust_feed