Coder Social home page Coder Social logo

bty's Introduction

bty

github crates.io docs.rs build status

Streamlined definition and usage of branded types in Rust.

This crate provides the Brand type and the brand! macro, which can be used to declare and seamlessly use branded types in Rust.

[dependencies]
bty = "0.1"

Supports rustc 1.60+

Example

The brand! macro may be used to declare branded types, which will be discriminated based on the name of the type alias.

bty::brand!(
    type UserId = i32;
);

Instances of UserId may be constructed using one of the deserialization implementations, such as the serde one or the sqlx one. Manually instantiation, though unrecommended, can be done using the unchecked_from_raw associated function.

See this thread from Matt Pocock on Twitter for a more exemplified and intuitive view. Though it shows examples in TypeScript, the principles remain the same.

Rationale

It's not rare to have values that, although of the same type, belong to different domains. For example, a web application could use the i32 type to represent both user ids and order ids.

While this may seem reasonable, since those different domain types have the same type, one could easily pass a user id to a function expecting an order id.

Since Rust's type system is nominal, this problem could be avoided by introducing different types for each id. For example, one could have:

pub struct UserId(i32);

pub struct OrderId(i32);

Now the compiler statically ensures that a user id is never erroneously passed in place of an order id. Nice!

Though this approach suits most cases, it gets unwieldy as the number of custom id types grows since, for usability's sake, the type definition alone is rarely sufficient. For example, to Clone or Debug a custom id, one must implement those traits for all of the custom types.

#[derive(Clone, Debug)]
pub struct UserId(i32);

#[derive(Clone, Debug)]
pub struct OrderId(i32);

The problem worsens as the number of uses for the id types grows. For example, what about serde serialization and deserialization?

bty solves this problem by not having separate types for the branded types. Instead, a single Brand type is used. Defined as Brand<Tag, Raw>, it is generic over a Tag type, which discriminates values of different "brands" (i.e., domains) and the underlying type, represented by Raw.

For most Rust's commonly used traits, if Raw implements it, then so does Brand. This means if Raw implements Clone and Debug, Brand<_, Raw> will also have them implemented.

Following the previous example, one could use bty and have:

bty::brand!(
    pub type UserId = i32;
    pub type OrderId = i32;
);

There's nothing special with the i32 type. Just like manually defined structs, any type may be used to construct a branded type.

License

MIT License.

bty's People

Contributors

lffg avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.