Crate objectionable

Source
Expand description

Objectionable storage of ?Sized types inline inside allocated objects.

See BigBox and InlineBox for the crate’s central interface.

§Feature Flags

§Soundness & Memory Model

When the strict-provenance crate feature is enabled, this crate uses unstable APIs1 for sound execution under the experimental strict provenance memory model and to support passing the test suite under Miri.

When this feature is disabled, this crate tries to replicate the unstable methods using only those available in stable Rust. This method is reliable enough for compilation in a practical environment, but is considered unsound under the strict provenance memory model. This should not have an effect on typical use cases (as of Rust 1.80), but when interacting with strict provenance, the aforementioned feature is required.

Bear in mind that this project is developped as a hobby, and is not formally verified. There may be undiscovered unsoundness in untested edge cases. Issues and PRs are welcome.

§Examples

// we define the trait object (and impls) which our `BigBox` will contain.
trait Character {
    fn personality(&self) -> &'static str;
}

impl Character for u8 {
    fn personality(&self) -> &'static str {
        "very small"
    }
}

impl Character for [u8; 1000] {
    fn personality(&self) -> &'static str {
        "enormous"
    }
}

// implementing the unsafe trait `FromSized` is necessary for creating `BigBox` values,
// but there is thankfully a safe macro for this:
objectionable::impl_from_sized_for_trait_object!(dyn Character);

// to use `BigBox`, we have to configure it with an internal type and maximum inline size:
type MyBox = objectionable::BigBox<dyn Character, 32>;

// if we have a pre-allocated value, we can use `BigBox::new_boxed` to create a `BigBox` value:
let pre_boxed = Box::new(5_u8);
let pre_boxed = MyBox::new_boxed(pre_boxed);

// alternatively, we can use `BigBox::new` which will store the value inline if it is small enough:
let inline = MyBox::new(2_u8);
assert!(inline.is_inline() == true);

// but if the value is too large, it will be allocated on the heap via a standard `Box`:
let boxed = MyBox::new([2u8; 1000]);
assert!(boxed.is_inline() == false);

// accessing values is easy:
assert_eq!(Character::personality(pre_boxed.as_ref()), "very small");
assert_eq!(Character::personality(inline.as_ref()), "very small");
assert_eq!(Character::personality(boxed.as_ref()), "enormous");

  1. Notably, Rust’s strict_provenance and ptr_metadata features are enabled. 

Macros§

impl_from_sized_for_trait_object
Safely implements FromSized for trait objects.

Structs§

BigBox
Similar to Box<T>, but stores small values inline.
InlineBox
A box which stores its (small) value inline.
TooLarge
An error indicating a value was too large to fit in an InlineBox.

Enums§

BoxCapturealloc
Represents the result of a BigBox::take operation.

Traits§

FromSized
Allows construction of ?Sized values from Sized values.