Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions src/header/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ enum Cursor {
/// You may notice that `u16` may represent more than 32,768 values. This is
/// true, but 32,768 should be plenty and it allows us to reserve the top bit
/// for future usage.
type Size = usize;
type Size = u16;

/// This limit falls out from above.
const MAX_SIZE: usize = (1 << 15);
Expand All @@ -252,7 +252,7 @@ struct Pos {
/// bits is fine since we know that the `indices` vector will never grow beyond
/// that size.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct HashValue(usize);
struct HashValue(u16);

/// Stores the data associated with a `HeaderMap` entry. Only the first value is
/// included in this struct. If a header name has more than one associated
Expand Down Expand Up @@ -465,8 +465,6 @@ impl<T> HeaderMap<T> {
/// assert_eq!(12, map.capacity());
/// ```
pub fn with_capacity(capacity: usize) -> HeaderMap<T> {
assert!(capacity <= MAX_SIZE, "requested capacity too large");

if capacity == 0 {
HeaderMap {
mask: 0,
Expand All @@ -477,6 +475,7 @@ impl<T> HeaderMap<T> {
}
} else {
let raw_cap = to_raw_capacity(capacity).next_power_of_two();
assert!(raw_cap <= MAX_SIZE, "requested capacity too large");
debug_assert!(raw_cap > 0);

HeaderMap {
Expand Down Expand Up @@ -642,11 +641,11 @@ impl<T> HeaderMap<T> {

if cap > self.indices.len() {
let cap = cap.next_power_of_two();
assert!(cap < MAX_SIZE, "header map reserve over max capacity");
assert!(cap <= MAX_SIZE, "header map reserve over max capacity");
assert!(cap != 0, "header map reserve overflowed");

if self.entries.len() == 0 {
self.mask = cap - 1;
self.mask = cap as Size - 1;
self.indices = vec![Pos::none(); cap].into_boxed_slice();
self.entries = Vec::with_capacity(usable_capacity(cap));
} else {
Expand Down Expand Up @@ -1543,6 +1542,7 @@ impl<T> HeaderMap<T> {

#[inline]
fn grow(&mut self, new_raw_cap: usize) {
assert!(new_raw_cap <= MAX_SIZE, "requested capacity too large");
// This path can never be reached when handling the first allocation in
// the map.

Expand Down Expand Up @@ -3109,6 +3109,7 @@ impl<T> ops::IndexMut<usize> for RawLinks<T> {
impl Pos {
#[inline]
fn new(index: usize, hash: HashValue) -> Self {
debug_assert!(index < MAX_SIZE);
Pos {
index: index as Size,
hash: hash,
Expand Down Expand Up @@ -3136,7 +3137,7 @@ impl Pos {
#[inline]
fn resolve(&self) -> Option<(usize, HashValue)> {
if self.is_some() {
Some((self.index, self.hash))
Some((self.index as usize, self.hash))
} else {
None
}
Expand Down Expand Up @@ -3192,13 +3193,13 @@ fn to_raw_capacity(n: usize) -> usize {

#[inline]
fn desired_pos(mask: Size, hash: HashValue) -> usize {
hash.0 & mask
(hash.0 & mask) as usize
}

/// The number of steps that `current` is forward of the desired position for hash
#[inline]
fn probe_distance(mask: Size, hash: HashValue, current: usize) -> usize {
current.wrapping_sub(desired_pos(mask, hash)) & mask
current.wrapping_sub(desired_pos(mask, hash)) & mask as usize
}

fn hash_elem_using<K: ?Sized>(danger: &Danger, k: &K) -> HashValue
Expand All @@ -3224,7 +3225,7 @@ where
}
};

HashValue((hash & MASK) as usize)
HashValue((hash & MASK) as u16)
}

/*
Expand Down
12 changes: 12 additions & 0 deletions tests/header_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ fn reserve_over_capacity() {
headers.reserve(50_000); // over MAX_SIZE
}

#[test]
fn with_capacity_max() {
// The largest capacity such that (cap + cap / 3) < MAX_SIZE.
HeaderMap::<u32>::with_capacity(24_576);
}

#[test]
#[should_panic]
fn with_capacity_overflow() {
HeaderMap::<u32>::with_capacity(24_577);
}

#[test]
#[should_panic]
fn reserve_overflow() {
Expand Down