I am looking at the example of a Tokio Proto Server in the following link - https://tokio.rs/docs/getting-started/simple-server/ , specifically the fn decode
method:
impl Decoder for LineCodec {
type Item = String;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
if let Some(i) = buf.iter().position(|&b| b == b'\n') {
// remove the serialized frame from the buffer.
let line = buf.split_to(i);
// Also remove the '\n'
buf.split_to(1);
// Turn this data into a UTF string and return it in a Frame.
match str::from_utf8(&line) {
Ok(s) => Ok(Some(s.to_string())),
Err(_) => Err(io::Error::new(io::ErrorKind::Other,
"invalid UTF-8")),
}
} else {
Ok(None)
}
}
In this example, there are no request headers, the Codec is simply trying to find a delimiter ('\n') at the end of a request. However, for my usecase, each request that will be decoded will have a header, which in turn will indicate the actual length of the request body.
Since parsing the header itself requires processing, I would prefer not to do it ever single time decode is called while I am receiving bytes. I am not sure what the best practice would be here. Would it make sense to add a field on LineCodec, like cur_header: Option<Header>
, and refer to it while using the decode method? Would this cause any synchronization issues if multiple requests are incoming?
Please let me know.
Thank you.