mod constants;
mod generated_struct;
mod invalid;
pub use self::{generated_struct::HeaderName, invalid::InvalidHeaderName};
use shared_bytes::SharedStr;
const fn validate_static(bytes: &[u8]) -> Result<(), InvalidHeaderName> {
validate(bytes)
}
fn validate_with_normalized_percent_encoding(
string: &str,
) -> Result<Option<SharedStr>, InvalidHeaderName> {
validate(string.as_bytes()).map(|()| None)
}
const fn validate(bytes: &[u8]) -> Result<(), InvalidHeaderName> {
match crate::rfc::token::validate(bytes) {
Ok(()) => Ok(()),
Err(e) => Err(InvalidHeaderName { byte: e.byte }),
}
}
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};
#[test]
fn equals_ignores_case() {
let upper_case = HeaderName::from_static("Content-Type");
let lower_case = HeaderName::try_from(upper_case.as_str().to_ascii_lowercase()).unwrap();
assert_eq!(lower_case, upper_case);
}
#[test]
fn hash_ignores_case() {
let upper_case = HeaderName::from_static("Content-Type");
let lower_case = HeaderName::try_from(upper_case.as_str().to_ascii_lowercase()).unwrap();
assert_eq!(hash(&lower_case), hash(&upper_case));
}
fn hash<T: Hash>(t: &T) -> u64 {
let mut hasher = DefaultHasher::new();
t.hash(&mut hasher);
hasher.finish()
}
#[test]
fn generated_constants_are_valid() {
for constant in HeaderName::GENERATED_CONSTANTS
.iter()
.map(|c| c.clone().into_shared_str())
{
assert_matches!(HeaderName::try_from(constant.clone()), Ok(name) => assert_eq!(constant, name.as_str()));
}
}
}