#identifier #wrapper #tagged #zero-cost #id #identify #ressource

tagged-id

一个零成本的包装器,为资源标识符添加类型安全。

2 个不稳定版本

0.2.0 2024 年 8 月 26 日
0.1.0 2024 年 8 月 26 日

#4#tagged

每月 21 次下载

Unlicense OR MIT

14KB
388

tagged-id

一个零成本的包装器,为资源标识符添加类型安全。

为什么?

这解决了两个问题

  • 如果两个资源由相同的类型标识(例如,一个 User 和一个 Device,它们都由一个 i32 标识),它们可能在应用程序代码中错误地交换。编译器无法帮助您解决这个问题,但这当然是不正确的。
  • 当编写需要操作资源标识符的代码时,您通常需要查找 ID 的具体类型,以便编写函数签名和类型注解。在大多数情况下,ID 的本质并不重要,因此将其视为一个不透明类型更方便。

示例

use tagged_id::{Id, Identify};

struct User {
  id: Id<User>, // id is a i32
  some_field: String
}

impl Identifiable for User {
  type InnerId = i32;
}

struct Device {
  id: Id<Device>, // id is also a i32
  some_value: i32
}

impl Identifiable for Device {
  type InnerId = i32;
}

fn main() {
  let user_id: Id<User> = Id::new(42);
  let device_id: Id<Device> = Id::new(42);

  // This does not compile since the tags are different.
  assert_eq!(user_id, device_id);
}

Id<T> 继承内部类型的核心特质的实现。例如,如果 InnerIdCopy,那么 Id<T> 也是 Copy
Id<T> 只是带有特质约束的内部类型的新类型包装器,这使得它成为一个零成本的抽象。

Cargo 功能标志

  • smartstring:启用将字符串转换为 CompactStringFrom<&str> 实例。当禁用时,将启用 String 的实例。
  • serde:启用对 tagged-id 和支持它的依赖项(如 smartstring)的 serde 支持。
  • sqlx-{postgres,mysql,sqlite}:启用 EncodeDecode 实例,以便与相应的 sqlx 后端透明使用。

依赖项

~0.5–14MB
~200K SLoC