Skip to content

Commit 0bacc84

Browse files
committed
Doc new_uninitialized and fallible_with_capacity
1 parent 7d01f51 commit 0bacc84

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/raw/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,11 @@ where
10721072
}
10731073

10741074
impl<A> RawTableInner<A> {
1075+
/// Creates a new empty hash table without allocating any memory.
1076+
///
1077+
/// In effect this returns a table with exactly 1 bucket. However we can
1078+
/// leave the data pointer dangling since that bucket is never written to
1079+
/// due to our load factor forcing us to always have at least 1 free bucket.
10751080
#[inline]
10761081
const fn new_in(alloc: A) -> Self {
10771082
Self {
@@ -1086,6 +1091,18 @@ impl<A> RawTableInner<A> {
10861091
}
10871092

10881093
impl<A: Allocator + Clone> RawTableInner<A> {
1094+
/// Allocates a new [`RawTableInner`] with the given number of buckets.
1095+
/// The control bytes are left uninitialized.
1096+
///
1097+
/// # Safety
1098+
///
1099+
/// The caller of this function must ensure that the `buckets` is power of two
1100+
/// and also initialize all control bytes of the length `self.bucket_mask + 1 +
1101+
/// Group::WIDTH` with the [`EMPTY`] bytes.
1102+
///
1103+
/// See also [`Allocator`] API for other safety concerns.
1104+
///
1105+
/// [`Allocator`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html
10891106
#[cfg_attr(feature = "inline-more", inline)]
10901107
unsafe fn new_uninitialized(
10911108
alloc: A,
@@ -1106,6 +1123,7 @@ impl<A: Allocator + Clone> RawTableInner<A> {
11061123
Err(_) => return Err(fallibility.alloc_err(layout)),
11071124
};
11081125

1126+
// SAFETY: null pointer will be caught in above check
11091127
let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
11101128
Ok(Self {
11111129
ctrl,
@@ -1116,6 +1134,10 @@ impl<A: Allocator + Clone> RawTableInner<A> {
11161134
})
11171135
}
11181136

1137+
/// Attempts to allocate a new [`RawTableInner`] with at least enough
1138+
/// capacity for inserting the given number of elements without reallocating.
1139+
///
1140+
/// All the control bytes are initialized with the [`EMPTY`] bytes.
11191141
#[inline]
11201142
fn fallible_with_capacity(
11211143
alloc: A,
@@ -1126,11 +1148,16 @@ impl<A: Allocator + Clone> RawTableInner<A> {
11261148
if capacity == 0 {
11271149
Ok(Self::new_in(alloc))
11281150
} else {
1151+
// SAFETY: We checked that we could successfully allocate the new table, and then
1152+
// initialized all control bytes with the constant `EMPTY` byte.
11291153
unsafe {
11301154
let buckets =
11311155
capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?;
11321156

11331157
let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?;
1158+
// SAFETY: We checked that the table is allocated and therefore the table already has
1159+
// `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
1160+
// so writing `self.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
11341161
result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes());
11351162

11361163
Ok(result)

0 commit comments

Comments
 (0)