2个不稳定版本
0.2.0 | 2019年11月9日 |
---|---|
0.1.0 | 2019年11月6日 |
在Rust模式中排名#1313
每月下载量41
用于test-binary-features
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
的好处
- 定义newtype所需的开销非常小。
- 通过原型提供的可重用语义。一旦你习惯了,比如金额,并知道它们能做什么,你就不需要花费脑力去理解你代码中其他类型的金额。
- 没有宏会弄乱你的命名空间。
实现特质
特质\原型 | 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的设计选择,该库采用的方法有一些限制
- 无法为使用
phantom-newtype
提供的原型锻造的类型实现额外的特质。每个所需的特质的组合都需要一个新的原型。 - 无法自定义原型的特质的实现。使用
phantom-newtype
,每个newtype都会继承其表示(包括Debug
和Display
)的实现。
依赖项
~170KB