Update docs, tests, and improve conversion to UUIDs.
This commit is contained in:
parent
02b99ba010
commit
8bbad764c3
4 changed files with 27 additions and 15 deletions
|
@ -12,6 +12,9 @@ readme = "README.md"
|
||||||
license-file = "LICENSE.md"
|
license-file = "LICENSE.md"
|
||||||
repository = "https://git.kittencollective.com/nebkor/julid-rs"
|
repository = "https://git.kittencollective.com/nebkor/julid-rs"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["serde", "sqlx"] # just the regular crate
|
default = ["serde", "sqlx"] # just the regular crate
|
||||||
serde = ["dep:serde"]
|
serde = ["dep:serde"]
|
||||||
|
@ -51,6 +54,3 @@ harness = false
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "julid-gen"
|
name = "julid-gen"
|
||||||
path = "src/bin/gen.rs"
|
path = "src/bin/gen.rs"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
all-features = true
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ Blog post: <https://proclamations.nebcorp-hias.com/sundries/presenting-julids/>
|
||||||
|
|
||||||
As of June of 2025, they can also be converted to and from [version 7
|
As of June of 2025, they can also be converted to and from [version 7
|
||||||
UUIDs](https://www.ietf.org/rfc/rfc9562.html#name-uuid-version-7), though some precision in the
|
UUIDs](https://www.ietf.org/rfc/rfc9562.html#name-uuid-version-7), though some precision in the
|
||||||
intra-millisecond counter is lost when going to a UUID.
|
intra-millisecond counter is lost when going to a UUID, via the `uuid` optional feature.
|
||||||
|
|
||||||
## A slightly deeper look
|
## A slightly deeper look
|
||||||
|
|
||||||
|
|
27
src/lib.rs
27
src/lib.rs
|
@ -2,18 +2,27 @@
|
||||||
use sqlite_loadable::prelude::{c_char, c_uint, sqlite3, sqlite3_api_routines};
|
use sqlite_loadable::prelude::{c_char, c_uint, sqlite3, sqlite3_api_routines};
|
||||||
|
|
||||||
mod base32;
|
mod base32;
|
||||||
|
|
||||||
|
/// Contains the [`Julid`] type, which is publicly exported at the top level.
|
||||||
pub mod julid;
|
pub mod julid;
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
/// Serialization into bytes, and deserialization from a variety of formats,
|
/// Serialization into bytes, and deserialization from a variety of formats,
|
||||||
/// with Serde (feature `serde` (default))
|
/// with Serde (feature `serde` (default))
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
#[cfg(feature = "sqlx")]
|
|
||||||
/// Traits from the SQLx crate for getting Julids into and out of SQLite
|
/// Traits from the SQLx crate for getting Julids into and out of SQLite
|
||||||
/// databases from normal Rust applications. (feature `sqlx` (default))
|
/// databases from normal Rust applications. (feature `sqlx` (default))
|
||||||
|
#[cfg(feature = "sqlx")]
|
||||||
pub mod sqlx;
|
pub mod sqlx;
|
||||||
#[cfg(feature = "uuid")]
|
|
||||||
/// UUIDv7s are almost as good as Julids, and can be interconverted almost
|
/// UUIDv7s are almost as good as Julids, and can be interconverted almost
|
||||||
/// perfectly.
|
/// perfectly. (feature `uuid` (non-default))
|
||||||
|
///
|
||||||
|
/// See the [`Julid::as_uuid`] and [`Julid::from_uuid`] methods for
|
||||||
|
/// converting a Julid to a UUID and constructing a Julid from a UUID
|
||||||
|
/// respectively.
|
||||||
|
#[cfg(feature = "uuid")]
|
||||||
pub mod uuid;
|
pub mod uuid;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -21,13 +30,13 @@ pub use base32::DecodeError;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use julid::Julid;
|
pub use julid::Julid;
|
||||||
|
|
||||||
/// The number of bits in a Julid's time portion
|
/// The number of bits in a Julid's millisecond timestamp (48)
|
||||||
pub const TIME_BITS: u8 = 48;
|
pub const TIME_BITS: u8 = 48;
|
||||||
/// The number of bits in the monotonic counter for intra-millisecond IDs
|
/// The number of bits in the monotonic counter for intra-millisecond IDs (16)
|
||||||
pub const COUNTER_BITS: u8 = 16;
|
pub const COUNTER_BITS: u8 = 16;
|
||||||
/// The number of random bits + bits in the monotonic counter
|
/// The number of random bits + bits in the monotonic counter (80)
|
||||||
pub const UNIQUE_BITS: u8 = 80;
|
pub const UNIQUE_BITS: u8 = 80;
|
||||||
/// The number of fully random bits
|
/// The number of fully random bits (64)
|
||||||
pub const RANDOM_BITS: u8 = 64;
|
pub const RANDOM_BITS: u8 = 64;
|
||||||
|
|
||||||
/// This `unsafe extern "C"` function is the main entry point into the loadable
|
/// This `unsafe extern "C"` function is the main entry point into the loadable
|
||||||
|
@ -52,7 +61,7 @@ pub unsafe extern "C" fn sqlite3_julid_init(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The code for the SQLite plugin is kept in this module, and exposed via the
|
/// The code for the SQLite plugin is kept in this module, and exposed via the
|
||||||
/// `sqlite3_julid_init` function (feature `plugin`)
|
/// [`sqlite3_julid_init`] function (feature `plugin` (non-default))
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub mod sqlite_plugin {
|
pub mod sqlite_plugin {
|
||||||
use sqlite_loadable::{
|
use sqlite_loadable::{
|
||||||
|
|
|
@ -13,7 +13,7 @@ impl Julid {
|
||||||
/// means that some bits in the original Julid are overwritten with
|
/// means that some bits in the original Julid are overwritten with
|
||||||
/// UUID-specific values, but only six bits in total are potentially
|
/// UUID-specific values, but only six bits in total are potentially
|
||||||
/// altered.
|
/// altered.
|
||||||
pub fn as_uuid(&self) -> Uuid {
|
pub const fn as_uuid(&self) -> Uuid {
|
||||||
let counter_mask = (1 << 12) - 1;
|
let counter_mask = (1 << 12) - 1;
|
||||||
let entropy_mask = (1 << 62) - 1;
|
let entropy_mask = (1 << 62) - 1;
|
||||||
let timestamp = self.timestamp();
|
let timestamp = self.timestamp();
|
||||||
|
@ -29,7 +29,9 @@ impl Julid {
|
||||||
///
|
///
|
||||||
/// UUIDv7s are very similar to Julids, but use 12 bits for a monotonic
|
/// UUIDv7s are very similar to Julids, but use 12 bits for a monotonic
|
||||||
/// counter instead of 16, and only 62 bits of entropy vs Julids' 64.
|
/// counter instead of 16, and only 62 bits of entropy vs Julids' 64.
|
||||||
/// Therefore, no bits need to be altered when converting to a Julid.
|
/// Therefore, no bits technically need to be altered when converting to a
|
||||||
|
/// Julid, but we zero out the high bits of the counter where the UUID
|
||||||
|
/// version was stored.
|
||||||
pub fn from_uuid(id: Uuid) -> Result<Self, UuidError> {
|
pub fn from_uuid(id: Uuid) -> Result<Self, UuidError> {
|
||||||
let ver = id.get_version_num();
|
let ver = id.get_version_num();
|
||||||
if ver != 7 {
|
if ver != 7 {
|
||||||
|
@ -107,6 +109,7 @@ mod test {
|
||||||
assert_eq!(j1.timestamp(), ju1.timestamp());
|
assert_eq!(j1.timestamp(), ju1.timestamp());
|
||||||
assert_eq!(j1.counter(), ju1.counter());
|
assert_eq!(j1.counter(), ju1.counter());
|
||||||
assert_eq!(j1.random() << 2, ju1.random() << 2);
|
assert_eq!(j1.random() << 2, ju1.random() << 2);
|
||||||
|
assert_eq!(ju1.random() >> 62, 2);
|
||||||
// once we've converted to uuid and then back to julid, we've reached the fixed
|
// once we've converted to uuid and then back to julid, we've reached the fixed
|
||||||
// point
|
// point
|
||||||
let u2 = ju1.as_uuid();
|
let u2 = ju1.as_uuid();
|
||||||
|
|
Loading…
Reference in a new issue