2 个版本

0.6.1 2021年7月5日
0.6.0 2021年7月5日

#1174命令行工具

BlueOak-1.0.0 OR Apache-2.0

23KB
322

ulid-lite

关于

ULID ("Universally Unique Lexicographically Sortable Identifier") 标准的实现。

ULID 是

  • 128 位兼容 UUID
  • 每毫秒有 1.21e+24 个唯一的 ULID
  • 可按字典序排序!
  • 规范编码为 26 个字符的字符串,而不是 36 个字符的 UUID
  • 使用 Crockford 的 base32 以提高效率和可读性(每个字符 5 位)
  • 不区分大小写
  • 没有特殊字符(URL 安全)

用法

从命令行

捆绑的应用程序生成一个 ULID 并将其打印到 stdout

$ ulid
01F5QNHN4G55VHQHA8XG1N6H9H

从 Rust

以下是一个使用此软件包的简单应用程序

use ulid::ulid;

fn main() {
    println!("{}", ulid());
}

主要的 API 是 ulid() 函数,它返回一个 String。如果您需要访问单个位,则调用 ulid_raw()

ulid::ulid() -> String
ulid::ulid_raw() -> u128

为了获得更多控制,还提供了 ulid::Ulid 类型。

ulid::Ulid::new() -> ulid::Ulid

Ulid 结构体是围绕一个 u128 的包装,并具有一些额外的方法。

let id = ulid::Ulid::new();

// They implement Display, LowerHex and UpperHex
println!("{}", id);
println!("{:x}", id);
println!("{:X}", id);

较新的 ULID 比较旧的 ULID 高

use std::thread::sleep;
use std::time::Duration;

let a = ulid();
sleep(Duration::from_millis(1));
let b = ulid();
assert!(a < b);

要生成多个 ulid::Ulid 值,建议使用 UlidGenerator。它提供了初始化内部伪随机数生成器的功能。

// use the system's clock as the initial seed...
let mut ulid_gen = ulid::UlidGenerator::new();
let ulids: Vec<_> = ulid_gen.take(1000).collect();
// ...or use a fixed initial seed
let mut ulid_gen = ulid::UlidGenerator::from_seed(12345);
let ulid = ulid_gen.ulid();

从 C

lib/ulid.h 处有可用的 C API。以下是一个生成并打印 ULID 的简单应用程序

#include <stdio.h>
#include "ulid.h"

int main(void) {
    char str[27];

    ulid_ctx ctx = ulid_init(0);
    ulid_write_new(&ctx, str, sizeof(str));

    printf("%s\n", str);

    return 0;
}

libulid 还提供了创建二进制(128 位)ULID 并将这些 ULID 转换为字符串的功能(此示例故意复杂以展示错误处理)

#include <stdio.h>
#include "ulid.h"

int main(void) {
    ulid_ctx ctx;
    ulid_t id;
    char buf[64], *cur = buf;
    int n, size = sizeof(buf);

    ctx = ulid_init(0);
    ulid_new(&ctx, &id);

    n = snprintf(cur, size, "Your ULID is ");
    if (n >= size)
        return 1;
    cur += n;
    size -= n;

    n = ulid_write(&id, cur, size);
    if (n < 0) /* failed, typically buffer is too small */
        return 1;
    cur += n;
    size -= n;

    n = snprintf(cur, size, ".");
    if (n >= size)
        return 1;

    printf("%s\n", buf);
    return 0;
}

安装

ulid-lite 添加到您的 crate 的 Cargo.toml 文件中

[dependencies]
ulid-lite = "0.6.1"

从源代码构建

您可以直接从上游仓库的主分支下载和安装 ulid-lite

$ cargo install --git https://github.com/timClicks/ulid-lite.git

构建 C 接口

要重新生成 ulid.h 头文件,运行 make lib/ulid.h

要构建 libulid 共享库,运行 make target/release/libulid.so

贡献

非常欢迎以任何形式为项目做出贡献,但是您必须遵守Rust行为准则

非代码贡献

您的贡献非常重要!请提交一个包含您建议的更改的问题

代码贡献

注意:这些说明仅在Ubuntu上进行了测试,请为其他操作系统提交纠正/改进。

设置开发环境

开始之前,您需要以下工具

  • 一个包含rustcrustupcargo的Rust安装
  • git
  • make

从项目的根目录开始,运行setup-devenv来安装由cargorustup管理的依赖项,例如MIRI

$ ./setup-devenv

提交更改

ulid-lite遵循GitHub的标准代码更改工作流程。请在此处提交一个分支,将提交推送到该分支,然后提交一个拉取请求(PR)。

在提交PR之前,您应该从项目的根目录运行make test && make,而不是cargo test。这将确保MIRI测试运行正确,并且所有工件都可以构建。

路线图

PostgreSQL扩展

我想使用这个crate开发pg_ulid扩展。

更多功能

  • 解析现有的ULIDs
  • 同一毫秒内的单调性
  • 溢出检查

更多平台

ulid-lite目前仅针对Linux进行构建。欢迎提交补丁以支持更多平台。

为什么添加另一个crate?

我想实现一个具有极简感的crate。它旨在易于构建且速度快。ulid-lite有最少的依赖项。这保持了构建时间的快速和二进制文件大小的较小。

ulid编译时间不长

$ cargo clean
$ cargo build --release
   Compiling libc v0.2.94
   Compiling lazy_static v0.2.11
   Compiling rand v0.4.6
   Compiling rand v0.3.23
   Compiling xorshift v0.1.3
   Compiling ulid-lite v0.4.0 (/.../ulid-lite)
    Finished release [optimized] target(s) in 5.68s

然而,更重要的是,ulid-lite非常快。单个CPU核心可以每毫秒生成大约35,700个ULIDs。

$ cargo bench
...
running 2 tests
test benchmark_generation ... bench:          28 ns/iter (+/- 2)
test benchmark_serialized ... bench:          71 ns/iter (+/- 12)

致谢

我在开发ulid-lite时依赖了另外两个实现

Dylan Hart github.com/dylanhart/ulid-rs
Marcos Macedo github.com/mmacedoeu/rulid.rs

依赖项

~370–600KB