https://github.com/adinack/bundle
A multi-type container with a static size.
https://github.com/adinack/bundle
embedded-rust no-std static-types
Last synced: about 1 year ago
JSON representation
A multi-type container with a static size.
- Host: GitHub
- URL: https://github.com/adinack/bundle
- Owner: AdinAck
- Archived: true
- Created: 2023-10-31T17:48:12.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-02-10T00:43:03.000Z (over 2 years ago)
- Last Synced: 2025-02-21T21:38:44.322Z (over 1 year ago)
- Topics: embedded-rust, no-std, static-types
- Language: Rust
- Homepage:
- Size: 41 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# bundle
A multi-type container with a static size.
## no_std
This crate is intended for use in `no_std` environments.
# Motivation
Trait objects require dynamic memory allocation since the concrete type being dispatched is not known until runtime.
For `no_std` environments, a global allocator may be limited, or not available at all. But dynamic dispatch may still be desired.
# Solution
This crate provides an attribute macro for generating an enum type that contains a finite set of concrete types.
Each variant of the enum corresponds to a type, in the form of a tuple variant.
Rust enums occupy as much space as the largest variant:
```rust
enum MultipleTypes {
A(A),
B(B),
C(C),
D(D)
}
```
Memory:
```
|# <- A
|### <- B
|## <- C
|##### <- D
##|##### < Total size
^
|
padding/tag
```
# Usage
## Basic
To create a bundle, simply mark an enum as a such:
```rust
trait Foo {
fn bar(&self) -> u8;
}
#[bundle]
enum MyBundle {
FirstType,
SecondType,
ThirdType
}
```
Now you can invoke methods defined by the shared trait:
```rust
impl Foo for FirstType {
fn bar(&self) -> u8 {
0
}
}
impl Foo for SecondType {
fn bar(&self) -> u8 {
1
}
}
impl Foo for ThirdType {
fn bar(&self) -> u8 {
2
}
}
let bundle: MyBundle = { /* fetch bundle from somewhere... */ }
let bar = use_my_bundle!(bundle, |inner| { inner.bar() }); // will be 0, 1, or 2 depending on what's in the bundle
```
## Other macros
Bundles can still be used with other macros as long as the bundle is the first one executed.
For example, use with `derive` where types `A`, `B` and `C` implement `Clone`:
```rust
#[bundle] // this goes first so derive sees the transformed enum
#[derive(Clone)]
enum MyBundle {
A,
B,
C,
}
```
## Generics
If generics are required for your bundle, you can add them like so:
```rust
#[bundle]
enum MyBundle {
A(A), // notice you must now create the tuple variant yourself
B,
C(C),
}
```
# Design Considerations
## Safety
The `#[bundle]` macro cannot generate unsafe code.