Skip to content

Commit

Permalink
add rust implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
carderne committed Jul 10, 2024
1 parent d8503bb commit 0adfad9
Show file tree
Hide file tree
Showing 9 changed files with 721 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# custom
scripts/

# rust generated files
target/

# python generated files
__pycache__/
*.py[oc]
Expand Down
75 changes: 75 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
resolver = "2"
members = [
"upid_rs",
]
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
run:
@rye run python -m upid
@cargo run -q
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# UPID

pronounced YOO-pid

**aka Universally Unique Prefixed Lexicographically Sortable Identifier**

This is the spec and Python implementation for UPID.
Expand All @@ -9,11 +11,16 @@ UPID is based on [ULID](https://github.com/ulid/spec) but with some modification
The core idea is that a **meaningful prefix** is specified that is stored in a 128-bit UUID-shaped slot.
Thus a UPID is **human-readable** (like a Stripe ID), but still efficient to store, sort and index.

UPID allows a prefix of up to **4 characters** (will be right-padded if shorter than 4), includes a non-wrapping timestamp with about 100 millisecond precision, and 64 bits of entropy.
UPID allows a prefix of up to **4 characters** (will be right-padded if shorter than 4), includes a non-wrapping timestamp with about 300 millisecond precision, and 64 bits of entropy.

This is a UPID:
This is a UPID in Python:
```python
upid("user") # user_aaccvpp5guht4dts56je5a
upid("user") # user_aaccvpp5guht4dts56je5a
```

And in Rust:
```rust
UPID::new("user") // user_aaccvpp5guht4dts56je5a
```

## Specification
Expand Down Expand Up @@ -57,12 +64,15 @@ Key changes relative to ULID:
### Collision
Relative to ULID, the time precision is reduced from 48 to 40 bits (keeping the most significant bits, so oveflow still won't occur until 10889 AD), and the randomness reduced from 80 to 64 bits.

The timestamp precision at 40 bits is around 100 milliseconds. In order to have a 50% probability of collision with 64 bits of randomness, you would need to generate around **4 billion items per 100 millisecond window**.
The timestamp precision at 40 bits is around 300 milliseconds. In order to have a 50% probability of collision with 64 bits of randomness, you would need to generate around **4 billion items per 100 millisecond window**.

## Python implementation
This aims to be maximally simple to convey the core working of the spec.
The current Python implementation is entirely based on [mdomke/python-ulid](https://github.com/mdomke/python-ulid).

## Rust implementation
The current Rust implementation is based on [dylanhart/ulid-rs](https://github.com/dylanhart/ulid-rs), but using the same lookup base32 lookup method as the Python implementation.

## Development
```bash
rye sync
Expand Down
7 changes: 7 additions & 0 deletions upid_rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "upid"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = { version = "0.8" }
Loading

0 comments on commit 0adfad9

Please sign in to comment.