Skip to main content

ntex_httparse/
version.rs

1use crate::{Error, Result, State, Status, iter::Bytes};
2
3#[inline]
4/// Parse an HTTP version, `HTTP/1.0` or `HTTP/1.1`.
5///
6/// Returns `0` for HTTP/1.0 and `1` for HTTP/1.1.
7pub fn parse_version(src: &[u8]) -> Result<u8> {
8    let mut st = State::default();
9    let mut bytes = Bytes::new(src, &mut st);
10    parse_version_inner(&mut bytes)
11}
12
13#[inline]
14#[allow(missing_docs)]
15pub(crate) fn parse_version_inner(bytes: &mut Bytes<'_, '_>) -> Result<u8> {
16    if let Some(eight) = bytes.peek_n::<8>() {
17        const H10: u64 = u64::from_ne_bytes(*b"HTTP/1.0");
18        const H11: u64 = u64::from_ne_bytes(*b"HTTP/1.1");
19        // peek_n before ensures within bounds
20        bytes.advance(8);
21        return match u64::from_ne_bytes(eight) {
22            H10 => Ok(Status::Complete(0)),
23            H11 => Ok(Status::Complete(1)),
24            _ => Err(Error::Version),
25        };
26    }
27
28    // else (but not in `else` because of borrow checker)
29
30    // If there aren't at least 8 bytes, we still want to detect early
31    // if this is a valid version or not. If it is, we'll return Partial.
32    expect!(bytes.next() == b'H' => Err(Error::Version));
33    expect!(bytes.next() == b'T' => Err(Error::Version));
34    expect!(bytes.next() == b'T' => Err(Error::Version));
35    expect!(bytes.next() == b'P' => Err(Error::Version));
36    expect!(bytes.next() == b'/' => Err(Error::Version));
37    expect!(bytes.next() == b'1' => Err(Error::Version));
38    expect!(bytes.next() == b'.' => Err(Error::Version));
39    Ok(Status::Partial)
40}