#unique-identifier #unique-id #globally #safe #k-sortable

type-safe-id

A type-safe, K-sortable, globally unique identifier

6 releases (3 breaking)

0.3.0 Apr 22, 2024
0.2.1 Jul 6, 2023
0.1.1 Jun 29, 2023
0.0.0 Jun 29, 2023

#1 in #globally

Download history 517/week @ 2024-07-21 1483/week @ 2024-07-28 462/week @ 2024-08-04 480/week @ 2024-08-11 345/week @ 2024-08-18 292/week @ 2024-08-25 586/week @ 2024-09-01 378/week @ 2024-09-08 552/week @ 2024-09-15 830/week @ 2024-09-22 933/week @ 2024-09-29 639/week @ 2024-10-06 545/week @ 2024-10-13 819/week @ 2024-10-20 341/week @ 2024-10-27 359/week @ 2024-11-03

2,077 downloads per month
Used in 10 crates (via pavex)

MIT/Apache

20KB
344 lines

type-safe-id

A type-safe, K-sortable, globally unique identifier.

Typed implementation of https://github.com/jetpack-io/typeid in Rust.

Examples

StaticType prefixes

This is the intended happy path. Using a StaticType implementation, you ensure that the ID being parsed is of the intended type.

use type_safe_id::{StaticType, TypeSafeId};

#[derive(Default)]
struct User;

impl StaticType for User {
    // must be lowercase ascii [a-z] only
    const TYPE: &'static str = "user";
}

// type alias for your custom typed id
type UserId = TypeSafeId<User>;

let user_id1 = UserId::new();
# std::thread::sleep(std::time::Duration::from_millis(10));
let user_id2 = UserId::new();

let uid1 = user_id1.to_string();
let uid2 = user_id2.to_string();
dbg!(&uid1, &uid2);
assert!(uid2 > uid1, "type safe IDs are ordered");

let user_id3: UserId = uid1.parse().expect("invalid user id");
let user_id4: UserId = uid2.parse().expect("invalid user id");

assert_eq!(user_id1.uuid(), user_id3.uuid(), "round trip works");
assert_eq!(user_id2.uuid(), user_id4.uuid(), "round trip works");

DynamicType prefixes

If you can't know what the prefix will be, you can use the DynamicType prefix.

use type_safe_id::{DynamicType, TypeSafeId};

let id: TypeSafeId<DynamicType> = "prefix_01h2xcejqtf2nbrexx3vqjhp41".parse().unwrap();

assert_eq!(id.type_prefix(), "prefix");
assert_eq!(id.uuid(), uuid::uuid!("0188bac7-4afa-78aa-bc3b-bd1eef28d881"));

Help

error[E0080]: evaluation of `<Index as type_safe_id::StaticType>::__TYPE_PREFIX_IS_VALID` failed
  --> /Users/conrad/Documents/code/type-safe-id/src/lib.rs:76:13
   |
76 |             assert!(Self::TYPE.as_bytes()[i].is_ascii_lowercase());
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: Self::TYPE.as_bytes()[i].is_ascii_lowercase()', /Users/conrad/Documents/code/type-safe-id/src/lib.rs:76:13

This compiler error suggests that your static type prefix is not valid because it contains non ascii-lowercase values.

error[E0080]: evaluation of `<Index as type_safe_id::StaticType>::__TYPE_PREFIX_IS_VALID` failed
  --> /Users/conrad/Documents/code/type-safe-id/src/lib.rs:73:9
   |
73 |         assert!(Self::TYPE.len() < 64);
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: Self::TYPE.len() < 64', /Users/conrad/Documents/code/type-safe-id/src/lib.rs:73:9
   |

This compiler error suggests that your static type prefix is not valid because it contains more than 63 characters.

Dependencies

~0.8–1.4MB
~29K SLoC