Rust RESP get_line analysis

if we look at simple tokio redis example (mini redis), we can see how the data is parsed. look at this

the resp is generally read something like this `+abc\r\n'

this is the code that actually crop down the buffer

fn get_line<'a>(src: &mut Cursor<&'a [u8]>) -> Result<&'a [u8], Error> {
    // Scan the bytes directly
    let start = src.position() as usize;
    // Scan to the second to last byte
    let end = src.get_ref().len() - 1;

    for i in start..end {
        if src.get_ref()[i] == b'\r' && src.get_ref()[i + 1] == b'\n' {
            // We found a line, update the position to be *after* the \n
            src.set_position((i + 2) as u64);

            // Return the line
            return Ok(&src.get_ref()[start..i]);
        }
    }

    Err(Error::Incomplete)
}

and I will show you how they works (algorithm)

variables setup

we have start and end, which consist of

let start = src.position() as usize;
let end = src.get_ref().len() - 1;

the src.position() always return 0, also depending on the context. src.get_ref().len() return the length of the buffer, for example, +rand\n\n has length 7.

because we wan't to read two chars at the end, which is \r and \n

so we substract length with 1, this is avoid buffer overflow

suppose this situation: buf: +rand\n\n

when we add everything with 1, we got this idx: 012345 6 7, it is idx[7]is found? no, so we need to sub with 1, the idx is something like this idx: 012345 6, no overflow

then we check the i and i + 1, make sure there is \r\n

set position

now, we set the cursor to the next incoming buffer. which after \r\n

src.set_position((i + 2) as u64);

suppose:

+rand\r\n+randomsomething\r\n
012345 6 ^ 
^^   ^   this is i + 2, indicates next buffer
ii+1 orig i