hyperium / hyperium/http

HeaderName from bytes unchecked support

Open
#857 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
1.4k
Forks
378
Avg merge
1d 21h
Merged PRs (30d)
5

Description

Hello,

I would like to request support for a function that accepts pre-validated HTTP header name tokens. This would allow parsers to skip redundant validation when bytes have already been validated upstream.

Proposed API

/// Converts a slice of bytes to an HTTP header name.
///
/// # Safety
///
/// The caller must ensure that `src` contains only valid HTTP header name tokens.
/// This allows the parser to skip validation and normalization for improved performance.
/// Passing invalid bytes will result in undefined behavior.
pub unsafe fn from_bytes_unchecked(src: &[u8]) -> Result<HeaderName, InvalidHeaderName> {
    let mut buf = uninit_u8_array();
    // SAFETY: see `from_bytes_unchecked` guarantees
    parse_hdr_unchecked(src, &mut buf)?
}

/// # Safety
///
/// The caller must ensure that `data` contains only valid HTTP header name tokens.
unsafe fn parse_hdr_unchecked<'a>(
    data: &'a [u8],
    b: &'a mut [MaybeUninit<u8>; SCRATCH_BUF_SIZE]
) -> Result<HeaderName, InvalidHeaderName> {
    match data.len() {
        0 => Err(InvalidHeaderName::new()),
        len @ 1..=SCRATCH_BUF_SIZE => {
            // Read from data into the buffer
            data.iter()
                .zip(b.iter_mut())
                .for_each(|(byte, out)| *out = MaybeUninit::new(*byte as usize));
            // SAFETY: len bytes of b were just initialized.
            let name: &'a [u8] = unsafe { slice_assume_init(&b[0..len]) };
            match StandardHeader::from_bytes(name) {
                Some(sh) => Ok(sh.into()),
                None => {
                    let buf = Bytes::copy_from_slice(name);
                    // SAFETY: see `parse_hdr_unchecked` guarantees
                    let val = unsafe { ByteStr::from_utf8_unchecked(buf) };
                    Ok(Custom(val).into())
                }
            }
        },
        SCRATCH_BUF_OVERFLOW..=super::MAX_HEADER_NAME_LEN => {
            use bytes::{BufMut};
            let mut dst = BytesMut::with_capacity(data.len());

            dst.extend_from_slice(data);

            // SAFETY: see `parse_hdr_unchecked` guarantees
            let val = unsafe { ByteStr::from_utf8_unchecked(dst.freeze()) };

            Ok(Custom(val).into())
        },
        _ => Err(InvalidHeaderName::new()),
    }
}

Motivation

Many HTTP parsers already perform validation of header name tokens during parsing. This function would allow those parsers to avoid duplicate validation by reusing the existing validation results. Additionally, the unchecked parser could return HeaderName directly, since the invariant of valid header tokens would be guaranteed by the caller.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the existing HeaderName byte-conversion and parsing APIs, then compare them with the proposed from_bytes_unchecked and parse_hdr_unchecked signatures. Review the safety and lifetime requirements before deciding how the unchecked path should integrate. Done means the API supports validated header-name bytes without redundant validation while preserving the stated invalid-input guarantees.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.