I want to extract the payload of a HTTP request as a Vec<u8>
. In the request, the payload is separated from the rest by the sequence \r\n\r\n
, that's why I want to split my Vec
at this position, and take the second element.
My current solution is to use the following function I wrote.
fn find_payload_index(buffer: &Vec<u8>) -> usize {
for (pos, e) in buffer.iter().enumerate() {
if pos < 3 {
continue
}
if buffer[pos - 3] == 13 && buffer[pos - 2] == 10 && buffer[pos - 1] == 13 && buffer[pos] == 10 {
return pos + 1;
}
}
0
}
13
is the ASCII value of \r
and 10
the value of \n
. I then split by the returned index. While this solution is technically working, it feels very unclean, and I was wondering how to do this in a more elegant way.
First of:
A function should almost never have a &Vec<_>
parameter.
Don't use the magic values 10 and 13, Rust supports byte literals: b'\r'
and b'\n'
.
As for your question: I believe you can make it a bit simpler using windows
and matches!
with a byte string literal pattern:
fn find_payload_index(buffer: &[u8]) -> Option<usize> {
buffer
.windows(4)
.enumerate()
.find(|(_, w)| matches!(*w, b"\r\n\r\n"))
.map(|(i, _)| i)
}
Permalink to the playground with test cases.