Recent Releases of https://github.com/bastidood/option-block

https://github.com/bastidood/option-block - 0.3.0

New Unchecked Getters

Users now have the option to skip the validation step when getting a reference to a value in the block. However, this should be sparingly used because it is unsafe. If improperly used, the method returns garbage memory, which may invoke undefined behavior.

```rust let mut block = option_block::Block8::default(); block.insert(0, 100);

// Safe! 👍 asserteq!(block.get(0), Some(&100)); asserteq!(unsafe { block.get_unchecked(0) }, &100);

// Undefined Behavior! ⚠ let _ = unsafe { block.get_unchecked(1) }; ```

- Rust
Published by BastiDood almost 4 years ago

https://github.com/bastidood/option-block - 0.2.2

Documentation Changes

  • Outdated documentation regarding the Clone implementation has been removed.
  • Added doc-comment about the iter method.
  • Clarified that the is_vacant method may panic when the given index is out of bounds.

- Rust
Published by BastiDood almost 4 years ago

https://github.com/bastidood/option-block - 0.2.1

This patch release mainly features documentation-related improvements. In particular, it has been made clearer that the iter module is not meant to be directly used. Rather, it is only part of the public interface so that users have the option to explicitly "name" the iterator objects in their code.

- Rust
Published by BastiDood almost 4 years ago

https://github.com/bastidood/option-block - 0.2.0

Undefined Behavior Resolved

This release fixes a critical oversight in the use of core::mem::MaybeUninit. Internally, option-block uses MaybeUninit to allocate an array which serves as the direct-address table on the stack.

However, the original implementation did not implement the Drop trait for the block variants. For non-trivial types with destructors (i.e. types that implement Drop), this leads to leaked memory and resources (at best). This is because MaybeUninit requires its contents to be manually dropped by the owner. In the worst case, however, the failure to invoke the Drop implementation leads to various (implementation-specific) undefined behavior.

```rust let mut block = option_block::Block8::::default(); block.insert(0, String::from("Hello"));

// This leaks the string because Drop was (originally) not implemented! // Internally, the MaybeUninit will simply ignore the String. // No destructors will be invoked. drop(block); ```

To address this, the various block variants now implement Drop. The implementation basically drops any valid elements left in the block.

Changes in Clone and Copy Bounds

Originally, all block variants implemented Clone and Copy as long as the inner data type T implements Copy. This is fine, but it is too restrictive. This release loosens the Clone trait bound. Now, as long as T implements Clone (no Copy necessary), the block variant will also implement Clone. In line with the resolved undefined behavior above, the Clone implementation is careful to only values that have been explicitly initialized (via insert or otherwise).

Note that since all block variants now implement Drop, it is now impossible to implement Copy. The compiler forbids types with destructors from implementing Copy (for good reason). Therefore, all block variants are no longer trivially Copy-able. This was an oversight from the original implementation.

FromIterator Implementation

For convenience, FromIterator<(usize, T) (for some T) has been implemented for all block variants. It is now possible to initialize a block from an iterator of key-value pairs.

rust let block: option_block::Block8<_> = [10, 8, 1] .into_iter() .enumerate() .collect(); assert_eq!(block.get(0), Some(&10)); assert_eq!(block.get(1), Some(&8)); assert_eq!(block.get(2), Some(&1)); assert!(block.get(3).is_none());

IntoIterator Implementation

The IntoIterator trait has also been implemented for Block (see into_iter mehotd) and &Block (see iter method). At the moment, there is no equivalent implementation for iter_mut due to some strange lifetime annotation issues. This will be sorted out in future releases.

```rust let block: optionblock::Block8<> = [10, 8, 1] .into_iter() .enumerate() .collect();

for val in &block { // Do stuff by-reference... }

for val in block { // Do stuff by-value... } ```

New Getter Methods

For convenience, new getters with default inserters have been added.

  • The main addition is the get_or_else method, which attempts to retrieve a value and return an exclusive reference to it. If the slot is vacant, then it constructs a new value based on the given closure.
  • Next is the get_or method, which is simply a special case of the get_or_else method where the value is ready upfront.
  • Finally, the get_or_default method provides a wrapper around get_or_else for inserting the default value if the slot is vacant.

rust let mut block = option_block::Block8::default(); assert_eq!(block.get_or_else(0, || 100), &mut 100); assert_eq!(block.get_or(1, 200), &mut 200); assert_eq!(block.get_or_default(2), &mut 0);

- Rust
Published by BastiDood almost 4 years ago