2个不稳定版本

0.2.0 2019年11月9日
0.1.0 2019年11月6日

Rust模式中排名#1313

每月下载量41
用于test-binary-features

Apache-2.0

38KB
471行代码(不包括注释)

phantom-newtype

无宏的轻量级newtype。

phantom-newtype是一个库,它提供了一种简单的方式来定义newtype。它不是newtype习语的替代品,而是一个很好的补充,它覆盖了常见的用例。

示例

// Amount and Id are "kinds" of newtypes people commonly use.
// Let's call them "archetypes".
use phantom_newtype::{Amount, Id, Instant};

// CentUnit here is just a marker that should never be constructed.
// It allows us to forge a new type of amounts.
enum CentUnit {}
type Cents = Amount<CentUnit, u64>;
//                            ^
//                            Representation used for `Cents`.

// Let's create another type of amounts.
// phantom-newtype is not a replacement for a powerful units library though.
enum YearUnit {}
type Years = Amount<YearUnit, u64>;

// Instants express the idea of time with respect to some point of reference.
// E.g. year of birth is instant but age is amount.
// Note that it is perfectly fine (and useful in practice) to use the same
// marker type for both instants and corresponding amounts.
type YearAD = Instant<YearUnit, u64>;

// Any type can be used as a marker, it's not necessary to always define
// fresh empty types.
type UserId = Id<User, u64>;
//                     ^
//                     Representation used for `Id`.

struct User {
    id: UserId,
    name: String,
    balance: Cents,
    age: Years,
}

impl User {
  fn new() -> Self {
      Self {
          id: UserId::from(1),
          name: "John".to_string(),
          balance: Cents::from(1000),
          age: Years::from(28),
          member_since: YearAD::from(2016),
      }
  }
}

// Tags used in archetypes can be useful in generic code.
fn load_by_id<EntityType>(id: Id<EntityType, u64>) -> EntityType;

使用phantom-newtype的好处

  1. 定义newtype所需的开销非常小。
  2. 通过原型提供的可重用语义。一旦你习惯了,比如金额,并知道它们能做什么,你就不需要花费脑力去理解你代码中其他类型的金额。
  3. 没有宏会弄乱你的命名空间。

实现特质

特质\原型 Amount<T, Repr> Id<T, Repr> Instant<T, Repr>
Default
Clone
Copy
Debug
Display
Eq
Ord
Hash
From<Repr>
Add<Self>
AddAssign<Self>
Sub<Self>
SubAssign<Self>
Mul<Repr>
MulAssign<Repr>
Div<Self>

Instants/Amounts算术

操作 输出类型
Instant<T, R> - Instant<T, R> Amount<单位,<R作为Sub>::输出>
Instant<T, R> - Amount<T, R2> Instant<单位,<R作为Sub<R2>>::输出>
Instant<T, R> + Amount<T, R2> Instant<单位,<R作为Add<R2>>::输出>

限制

由于Rust的设计选择,该库采用的方法有一些限制

  1. 无法为使用phantom-newtype提供的原型锻造的类型实现额外的特质。每个所需的特质的组合都需要一个新的原型。
  2. 无法自定义原型的特质的实现。使用phantom-newtype,每个newtype都会继承其表示(包括DebugDisplay)的实现。

依赖项

~170KB