Skip to content

HeaderName from bytes unchecked support #857

Description

@anemoiq

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions