#unsized #box #trait-object #alloc #no-alloc

no-std objectionable

objectionable storage of unsized types inline inside allocated objects

6 releases

0.3.1 Aug 23, 2024
0.3.0 Aug 23, 2024
0.2.4 Aug 23, 2024
0.1.0 Aug 3, 2024

#1258 in Rust patterns

MIT/Apache

31KB
415 lines

objectionable storage of ?Sized types inline inside allocated objects.

See the documentation for usage and examples.

License

Everything in this repository is dual-licensed under either:

at your option, unless explicitly stated otherwise.


lib.rs:

Objectionable storage of ?Sized types inline inside allocated objects.

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

Soundness & Memory Model

When the strict-provenance crate feature is enabled, this crate uses unstable APIs[^1] 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.

[^1]: Notably, Rust's strict_provenance and ptr_metadata features are enabled.

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");

Dependencies

~175KB