Struct hashbrown::raw::Bucket

source ·
pub struct Bucket<T> {
    ptr: NonNull<T>,
}
Expand description

A reference to a hash table bucket containing a T.

This is usually just a pointer to the element itself. However if the element is a ZST, then we instead track the index of the element in the table so that erase works properly.

Fields§

§ptr: NonNull<T>

Implementations§

source§

impl<T> Bucket<T>

source

const IS_ZERO_SIZED_TYPE: bool = _

source

unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self

Creates a Bucket that contain pointer to the data. The pointer calculation is performed by calculating the offset from given base pointer (convenience for base.as_ptr().sub(index)).

index is in units of T; e.g., an index of 3 represents a pointer offset of 3 * size_of::<T>() bytes.

If the T is a ZST, then we instead track the index of the element in the table so that erase works properly (return NonNull::new_unchecked((index + 1) as *mut T))

Safety

If mem::size_of::<T>() != 0, then the safety rules are directly derived from the safety rules for <*mut T>::sub method of *mut T and the safety rules of NonNull::new_unchecked function.

Thus, in order to uphold the safety contracts for the <*mut T>::sub method and NonNull::new_unchecked function, as well as for the correct logic of the work of this crate, the following rules are necessary and sufficient:

  • the base pointer must not be dangling and must points to the end of the first value element from the data part of the table, i.e. must be the pointer that returned by RawTable::data_end or by RawTableInner::data_end<T>;

  • index must not be greater than RawTableInner.bucket_mask, i.e. index <= RawTableInner.bucket_mask or, in other words, (index + 1) must be no greater than the number returned by the function RawTable::buckets or RawTableInner::buckets.

If mem::size_of::<T>() == 0, then the only requirement is that the index must not be greater than RawTableInner.bucket_mask, i.e. index <= RawTableInner.bucket_mask or, in other words, (index + 1) must be no greater than the number returned by the function RawTable::buckets or RawTableInner::buckets.

source

unsafe fn to_base_index(&self, base: NonNull<T>) -> usize

Calculates the index of a Bucket as distance between two pointers (convenience for base.as_ptr().offset_from(self.ptr.as_ptr()) as usize). The returned value is in units of T: the distance in bytes divided by core::mem::size_of::<T>().

If the T is a ZST, then we return the index of the element in the table so that erase works properly (return self.ptr.as_ptr() as usize - 1).

This function is the inverse of from_base_index.

Safety

If mem::size_of::<T>() != 0, then the safety rules are directly derived from the safety rules for <*const T>::offset_from method of *const T.

Thus, in order to uphold the safety contracts for <*const T>::offset_from method, as well as for the correct logic of the work of this crate, the following rules are necessary and sufficient:

  • base contained pointer must not be dangling and must point to the end of the first element from the data part of the table, i.e. must be a pointer that returns by RawTable::data_end or by RawTableInner::data_end<T>;

  • self also must not contain dangling pointer;

  • both self and base must be created from the same RawTable (or RawTableInner).

If mem::size_of::<T>() == 0, this function is always safe.

source

pub fn as_ptr(&self) -> *mut T

Acquires the underlying raw pointer *mut T to data.

Note

If T is not Copy, do not use *mut T methods that can cause calling the destructor of T (for example the <*mut T>::drop_in_place method), because for properly dropping the data we also need to clear data control bytes. If we drop data, but do not clear data control byte it leads to double drop when RawTable goes out of scope.

If you modify an already initialized value, so Hash and Eq on the new T value and its borrowed form must match those for the old T value, as the map will not re-evaluate where the new value should go, meaning the value may become “lost” if their location does not reflect their state.

Examples
use core::hash::{BuildHasher, Hash};
use hashbrown::raw::{Bucket, RawTable};

type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;

fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
    use core::hash::Hasher;
    let mut state = hash_builder.build_hasher();
    key.hash(&mut state);
    state.finish()
}

let hash_builder = NewHashBuilder::default();
let mut table = RawTable::new();

let value = ("a", 100);
let hash = make_hash(&hash_builder, &value.0);

table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));

let bucket: Bucket<(&str, i32)> = table.find(hash, |(k1, _)| k1 == &value.0).unwrap();

assert_eq!(unsafe { &*bucket.as_ptr() }, &("a", 100));
source

unsafe fn next_n(&self, offset: usize) -> Self

Create a new Bucket that is offset from the self by the given offset. The pointer calculation is performed by calculating the offset from self pointer (convenience for self.ptr.as_ptr().sub(offset)). This function is used for iterators.

offset is in units of T; e.g., a offset of 3 represents a pointer offset of 3 * size_of::<T>() bytes.

Safety

If mem::size_of::<T>() != 0, then the safety rules are directly derived from the safety rules for <*mut T>::sub method of *mut T and safety rules of NonNull::new_unchecked function.

Thus, in order to uphold the safety contracts for <*mut T>::sub method and NonNull::new_unchecked function, as well as for the correct logic of the work of this crate, the following rules are necessary and sufficient:

  • self contained pointer must not be dangling;

  • self.to_base_index() + ofset must not be greater than RawTableInner.bucket_mask, i.e. (self.to_base_index() + ofset) <= RawTableInner.bucket_mask or, in other words, self.to_base_index() + ofset + 1 must be no greater than the number returned by the function RawTable::buckets or RawTableInner::buckets.

If mem::size_of::<T>() == 0, then the only requirement is that the self.to_base_index() + ofset must not be greater than RawTableInner.bucket_mask, i.e. (self.to_base_index() + ofset) <= RawTableInner.bucket_mask or, in other words, self.to_base_index() + ofset + 1 must be no greater than the number returned by the function RawTable::buckets or RawTableInner::buckets.

source

pub(crate) unsafe fn drop(&self)

Executes the destructor (if any) of the pointed-to data.

Safety

See ptr::drop_in_place for safety concerns.

You should use RawTable::erase instead of this function, or be careful with calling this function directly, because for properly dropping the data we need also clear data control bytes. If we drop data, but do not erase data control byte it leads to double drop when RawTable goes out of scope.

source

pub(crate) unsafe fn read(&self) -> T

Reads the value from self without moving it. This leaves the memory in self unchanged.

Safety

See ptr::read for safety concerns.

You should use RawTable::remove instead of this function, or be careful with calling this function directly, because compiler calls its destructor when readed value goes out of scope. It can cause double dropping when RawTable goes out of scope, because of not erased data control byte.

source

pub(crate) unsafe fn write(&self, val: T)

Overwrites a memory location with the given value without reading or dropping the old value (like ptr::write function).

Safety

See ptr::write for safety concerns.

Note

Hash and Eq on the new T value and its borrowed form must match those for the old T value, as the map will not re-evaluate where the new value should go, meaning the value may become “lost” if their location does not reflect their state.

source

pub unsafe fn as_ref<'a>(&self) -> &'a T

Returns a shared immutable reference to the value.

Safety

See NonNull::as_ref for safety concerns.

Examples
use core::hash::{BuildHasher, Hash};
use hashbrown::raw::{Bucket, RawTable};

type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;

fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
    use core::hash::Hasher;
    let mut state = hash_builder.build_hasher();
    key.hash(&mut state);
    state.finish()
}

let hash_builder = NewHashBuilder::default();
let mut table = RawTable::new();

let value: (&str, String) = ("A pony", "is a small horse".to_owned());
let hash = make_hash(&hash_builder, &value.0);

table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));

let bucket: Bucket<(&str, String)> = table.find(hash, |(k, _)| k == &value.0).unwrap();

assert_eq!(
    unsafe { bucket.as_ref() },
    &("A pony", "is a small horse".to_owned())
);
source

pub unsafe fn as_mut<'a>(&self) -> &'a mut T

Returns a unique mutable reference to the value.

Safety

See NonNull::as_mut for safety concerns.

Note

Hash and Eq on the new T value and its borrowed form must match those for the old T value, as the map will not re-evaluate where the new value should go, meaning the value may become “lost” if their location does not reflect their state.

Examples
use core::hash::{BuildHasher, Hash};
use hashbrown::raw::{Bucket, RawTable};

type NewHashBuilder = core::hash::BuildHasherDefault<ahash::AHasher>;

fn make_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
    use core::hash::Hasher;
    let mut state = hash_builder.build_hasher();
    key.hash(&mut state);
    state.finish()
}

let hash_builder = NewHashBuilder::default();
let mut table = RawTable::new();

let value: (&str, String) = ("A pony", "is a small horse".to_owned());
let hash = make_hash(&hash_builder, &value.0);

table.insert(hash, value.clone(), |val| make_hash(&hash_builder, &val.0));

let bucket: Bucket<(&str, String)> = table.find(hash, |(k, _)| k == &value.0).unwrap();

unsafe {
    bucket
        .as_mut()
        .1
        .push_str(" less than 147 cm at the withers")
};
assert_eq!(
    unsafe { bucket.as_ref() },
    &(
        "A pony",
        "is a small horse less than 147 cm at the withers".to_owned()
    )
);

Trait Implementations§

source§

impl<T> Clone for Bucket<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T> Send for Bucket<T>

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for Bucket<T>where T: RefUnwindSafe,

§

impl<T> !Sync for Bucket<T>

§

impl<T> Unpin for Bucket<T>

§

impl<T> UnwindSafe for Bucket<T>where T: RefUnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.