Parsing

Now, let’s look at the parse_frame() function. Parsing is done in two steps.

  1. Ensure a full frame is buffered and find the end index of the frame.
  2. Parse the frame.

The mini-redis crate provides us with a function for both of these steps:

  1. Frame::check
  2. Frame::parse

We will also reuse the Buf abstraction to help. A Buf is passed into Frame::check. As the check function iterates the passed in buffer, the internal cursor will be advanced. When check returns, the buffer’s internal cursor points to the end of the frame.

For the Buf type, we will use std::io::Cursor<&[u8]>.

  1. use mini_redis::{Frame, Result};
  2. use mini_redis::frame::Error::Incomplete;
  3. use bytes::Buf;
  4. use std::io::Cursor;
  5. fn parse_frame(&mut self)
  6. -> Result<Option<Frame>>
  7. {
  8. // Create the `T: Buf` type.
  9. let mut buf = Cursor::new(&self.buffer[..]);
  10. // Check whether a full frame is available
  11. match Frame::check(&mut buf) {
  12. Ok(_) => {
  13. // Get the byte length of the frame
  14. let len = buf.position() as usize;
  15. // Reset the internal cursor for the
  16. // call to `parse`.
  17. buf.set_position(0);
  18. // Parse the frame
  19. let frame = Frame::parse(&mut buf)?;
  20. // Discard the frame from the buffer
  21. self.buffer.advance(len);
  22. // Return the frame to the caller.
  23. Ok(Some(frame))
  24. }
  25. // Not enough data has been buffered
  26. Err(Incomplete) => Ok(None),
  27. // An error was encountered
  28. Err(e) => Err(e.into()),
  29. }
  30. }

The full Frame::check function can be found here. We will not cover it in its entirety.

The relevant thing to note is that Buf‘s “byte iterator” style APIs are used. These fetch data and advance the internal cursor. For example, to parse a frame, the first byte is checked to determine the type of the frame. The function used is Buf::get_u8. This fetches the byte at the current cursor’s position and advances the cursor by one.

There are more useful methods on the Buf trait. Check the API docs for more details.