14 个版本 (破坏性更新)
0.12.0 | 2024 年 6 月 17 日 |
---|---|
0.11.0 | 2024 年 4 月 14 日 |
0.10.0 | 2024 年 3 月 6 日 |
0.5.0 | 2023 年 12 月 27 日 |
362 在 Rust 模式 中
每月 62 次下载
13KB
127 行
strong-type
strong-type
是一个 Rust 包,提供了宏来轻松创建具有命名和强类型的原始类型和字符串类型。强类型化有助于使代码更具表达性并减少错误,确保每种类型都按预期的方式使用。
use strong_type::StrongType;
#[derive(StrongType)]
struct Timestamp(i64);
let timestamp = Timestamp::new(1701620628123456789);
println!("{}", timestamp); // Timestamp(1701620628123456789)
功能
-
派生 trait
StrongType
: 创建一个命名强类型。- 该宏自动实现常见的特质,如
Clone
、Debug
、Default
、PartialEq
、PartialOrd
、Send
和Sync
。它还默认实现了Display
,除非被自定义_display 属性覆盖。 - 根据底层数据类型,条件性实现特质如
Copy
、Eq
、Ord
、Hash
。对于如i32
或bool
这样的原始数据类型,这些附加特质将被自动包含。 - 数值类型,包括整数和浮点数,还实现了常量
MIN
、MAX
、INFINITY
、NEG_INFINITY
和ZERO
。此外,对于浮点数类型,还实现了NAN
。
- 该宏自动实现常见的特质,如
-
属性
- 将以下属性添加到
#[strong_type(...)]
允许额外功能auto_operators
:自动实现相关算术(对于数值类型)或逻辑(对于布尔类型)运算符。addable
:自动实现Add
、Sub
和其他相关特质。该属性是auto_operators
的严格子集。可伸缩
:自动实现强类型结构体与其原始类型之间的Mul
、Div
、Rem
和其他相关特质的实现。请注意,此属性不是auto_operators
的子集。自定义显示
:允许用户手动实现Display
特质,提供默认显示格式的替代方案。转换
:自动为底层类型实现From
和Into
特质。这是可选的,因为转换可能会使强类型不那么明显。底层
:指定嵌套强类型的底层原始类型。
- 将以下属性添加到
安装
将strong-type
添加到您的Cargo.toml
[dependencies]
strong-type = "0.12"
支持底层类型
- 整数类型:
i8
、i16
、i32
、i64
、i128
、isize
- 无符号整数类型:
u8
、u16
、u32
、u64
、u128
、usize
- 浮点类型:
f32
、f64
- 布尔类型:
bool
字符
字符串
- 上述类型的强类型
示例
创建命名强类型
带有私有字段
use strong_type::StrongType;
#[derive(StrongType)]
struct Tag(String);
let tag = Tag::new("dev");
const TAG: Tag = Tag::const_new("prod");
带有公共字段
use strong_type::StrongType;
#[derive(StrongType)]
struct Timestamp(pub i64);
let timestamp = Timestamp(1701620628123456789);
println!("{}", timestamp); // Timestamp(1701620628123456789)
演示类型区别
use strong_type::StrongType;
use std::any::Any;
#[derive(StrongType)]
struct Second(i32);
#[derive(StrongType)]
struct Minute(i32);
let x = Second::new(2);
let y = Second::new(3);
let z = Minute::new(3);
assert_eq!(x.type_id(), y.type_id()); // Same type: Second
assert_ne!(y.type_id(), z.type_id()); // Different types: Second versus Minute
利用可散列性
use std::collections::HashSet;
#[derive(StrongType)]
struct Tag(String);
let mut map = HashSet::<Tag>::new();
map.insert(Tag::new("dev"));
map.insert(Tag::new("prod"));
assert_eq!(map.len(), 2);
具有算术操作的命名整型类型
use strong_type::StrongType;
#[derive(StrongType)]
#[strong_type(auto_operators)]
struct Nanosecond(u32);
let x = Nanosecond::new(2);
let y = Nanosecond::new(3);
let z = Nanosecond::default();
assert_eq!(x.value(), 2);
assert_eq!(y.value(), 3);
assert_eq!(z.value(), 0);
assert!(x < y);
assert!(y >= x);
assert_eq!(x + y, Nanosecond(5));
#[derive(StrongType)]
#[strong_type(scalable)]
struct Millisecond(u32);
let x = Millisecond::new(2);
assert_eq!(x * 3, Millisecond(6));
具有逻辑操作的命名布尔类型
use strong_type::StrongType;
#[derive(StrongType)]
#[strong_type(auto_operators)]
struct IsTrue(bool);
let x = IsTrue::new(true);
let y = IsTrue::new(false);
assert_eq!(x & y, IsTrue::new(false));
assert_eq!(x | y, IsTrue::new(true));
assert_eq!(x ^ y, IsTrue::new(true));
assert_eq!(!x, IsTrue::new(false));
使用custom_display
的自定义显示实现
use std::fmt::{Display, Formatter, Result};
use strong_type::StrongType;
#[derive(StrongType)]
#[strong_type(custom_display)]
struct Second(f64);
impl Display for Second {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "Second({:.2})", &self.0)
}
}
println!("{}", Second::new(std::f64::consts::E)); // "Second(2.72)"
println!("{:?}", Second::new(std::f64::consts::E)); // "Second { value: 2.718281828459045 }"
嵌套强类型
#[derive(StrongType)]
#[strong_type(auto_operators)]
struct Dollar(i32);
#[derive(StrongType)]
#[strong_type(auto_operators, underlying = i32)]
struct Cash(Dollar);
#[derive(StrongType)]
#[strong_type(underlying = i32)]
struct Coin(Cash);
注意事项
- 当使用
#[derive(StrongType)]
时,特质的Eq
和PartialEq
使用impl
实现。因此,StructuralEq
和StructuralPartialEq
尚未实现,阻止了与强类型原语的模式匹配。 #[strong_type(scalable)]
不适用于嵌套强类型。
依赖关系
~290–750KB
~18K SLoC