Skip to content

Commit

Permalink
Implement more HashSet constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
twe4ked committed Feb 19, 2020
1 parent 19443be commit d5a8049
Showing 1 changed file with 99 additions and 2 deletions.
101 changes: 99 additions & 2 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! See `HashSet` for details.

use std::borrow::Borrow;
use std::hash::Hash;
use std::hash::{BuildHasher, Hash};

use crate::epoch::{self, Guard};
use crate::iter::Keys;
Expand Down Expand Up @@ -48,6 +48,72 @@ where
map: HashMap<T, (), S>,
}

impl<T, S> Default for HashSet<T, S>
where
T: Sync + Send + Clone + Hash + Eq,
S: BuildHasher + Default,
{
fn default() -> Self {
Self::with_hasher(S::default())
}
}

impl<T, S> HashSet<T, S>
where
T: Sync + Send + Clone + Hash + Eq,
S: BuildHasher,
{
/// Creates an empty set which will use `hash_builder` to hash values.
///
/// The created set has the default initial capacity.
///
/// Warning: `hash_builder` is normally randomly generated, and is designed to
/// allow the set to be resistant to attacks that cause many collisions and
/// very poor performance. Setting it manually using this
/// function can expose a DoS attack vector.
///
/// # Examples
///
/// ```
/// use flurry::{HashSet, DefaultHashBuilder};
///
/// let set = HashSet::with_hasher(DefaultHashBuilder::default());
/// set.insert(1);
/// ```
pub fn with_hasher(hash_builder: S) -> Self {
Self {
map: HashMap::with_hasher(hash_builder),
}
}

/// Creates an empty set with the specified `capacity`, using `hash_builder` to hash the
/// values.
///
/// The set will be sized to accommodate `capacity` elements with a low chance of reallocating
/// (assuming uniformly distributed hashes). If `capacity` is 0, the call will not allocate,
/// and is equivalent to [`HashSet::new`].
///
/// Warning: `hash_builder` is normally randomly generated, and is designed to allow the set
/// to be resistant to attacks that cause many collisions and very poor performance.
/// Setting it manually using this function can expose a DoS attack vector.
///
/// # Examples
///
/// ```
/// use flurry::HashSet;
/// use std::collections::hash_map::RandomState;
///
/// let s = RandomState::new();
/// let set = HashSet::with_capacity_and_hasher(10, s);
/// set.insert(1);
/// ```
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
Self {
map: HashMap::with_capacity_and_hasher(capacity, hash_builder),
}
}
}

impl<T> HashSet<T, crate::DefaultHashBuilder>
where
T: Sync + Send + Clone + Hash + Eq,
Expand All @@ -63,10 +129,41 @@ where
/// ```
pub fn new() -> Self {
Self {
map: HashMap::<T, ()>::new(),
map: HashMap::default(),
}
}

/// Creates an empty `HashSet` with the specified capacity.
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
///
/// # Examples
///
/// ```
/// use flurry::HashSet;
///
/// let map: HashSet<&str> = HashSet::with_capacity(10);
/// ```
///
/// # Notes
///
/// There is no guarantee that the HashSet will not resize if `capacity`
/// elements are inserted. The set will resize based on key collision, so
/// bad key distribution may cause a resize before `capacity` is reached.
/// For more information see the [`resizing behavior`] of HashMap.
///
/// [`resizing behavior`]: index.html#resizing-behavior
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, crate::DefaultHashBuilder::default())
}
}

impl<T, S> HashSet<T, S>
where
T: Sync + Send + Clone + Hash + Eq,
S: BuildHasher,
{
/// Adds a value to the set.
///
/// If the set did not have this value present, true is returned.
Expand Down

0 comments on commit d5a8049

Please sign in to comment.