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

NameDescription
ArcStores anything in Arc<T>
RcStores anything in Rc<T>
BoxStores anything in Box<T>
InlineStores 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.