Tupperware
Tupperware is an experiment in Rust that allows you to define structs
without specifying how the fields are stored. This allows you to build
generic structs that be adapted to specific use-cases, for example storing
certain fields wrapped in an Arc for cheap immutable cloning in multithreaded
environments, while using Rc for single-threaded scenarios.
Documentation for it is available here.
Examples
For example, if you want to define a User struct which stores a user name and
a list of groups the user is part of, but you want to be generic over what container
those fields are stored in, you could define it like this:
#![allow(unused)] fn main() { use tupperware::Storage; enum Group { Admin, Supervisor, User, } pub struct User<S: Storage> { name: S::Type<str>, groups: S::Type<[Group]>, } }
With this definition, you can now swap in different variants of Storage to specify how
the fields should be stored. Here is a few examples:
#![allow(unused)] fn main() { // this is what User<Inline> would look like pub struct User { name: String, groups: Vec<Group>, } // this is what User<Arc> would look like pub struct User { name: Arc<str>, groups: Arc<[Group]>, } }
Storage Containers
| Name | Description |
|---|---|
Arc | Stores anything in Arc<T> |
Rc | Stores anything in Rc<T> |
Box | Stores anything in Box<T> |
Inline | Stores anything inline. Stores str as String, [T] as Vec<T>, Path as PathBuf, OsStr as OsString. |
Ref<'a> | Stores anything as &'a T. |
Use-Cases
I mainly wrote this crate to see if it could be done. It may have some
applications when writing async code, and you want to make it easy to switch at
compile time between thread-safe variants of your code (using Arc) and
single-threaded variants (using Rc) by using this trait in places where you
have data you want to clone and share with different async spawn points.
It might be useful to you, or it could give you some inspiration.