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