diff --git a/Cargo.toml b/Cargo.toml
index bafafd6..3d43103 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,9 @@ readme = "README.md"
license-file = "LICENSE.md"
repository = "https://git.kittencollective.com/nebkor/julid-rs"
+[package.metadata.docs.rs]
+all-features = true
+
[features]
default = ["serde", "sqlx"] # just the regular crate
serde = ["dep:serde"]
@@ -51,6 +54,3 @@ harness = false
[[bin]]
name = "julid-gen"
path = "src/bin/gen.rs"
-
-[package.metadata.docs.rs]
-all-features = true
diff --git a/README.md b/README.md
index 26f57e5..b579081 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ Blog post:
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
-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
diff --git a/src/lib.rs b/src/lib.rs
index c56e525..f04267b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,18 +2,27 @@
use sqlite_loadable::prelude::{c_char, c_uint, sqlite3, sqlite3_api_routines};
mod base32;
+
+/// Contains the [`Julid`] type, which is publicly exported at the top level.
pub mod julid;
-#[cfg(feature = "serde")]
+
/// Serialization into bytes, and deserialization from a variety of formats,
/// with Serde (feature `serde` (default))
+#[cfg(feature = "serde")]
pub mod serde;
-#[cfg(feature = "sqlx")]
+
/// Traits from the SQLx crate for getting Julids into and out of SQLite
/// databases from normal Rust applications. (feature `sqlx` (default))
+#[cfg(feature = "sqlx")]
pub mod sqlx;
-#[cfg(feature = "uuid")]
+
/// 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;
#[doc(inline)]
@@ -21,13 +30,13 @@ pub use base32::DecodeError;
#[doc(inline)]
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;
-/// 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;
-/// 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;
-/// The number of fully random bits
+/// The number of fully random bits (64)
pub const RANDOM_BITS: u8 = 64;
/// 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
-/// `sqlite3_julid_init` function (feature `plugin`)
+/// [`sqlite3_julid_init`] function (feature `plugin` (non-default))
#[cfg(feature = "plugin")]
pub mod sqlite_plugin {
use sqlite_loadable::{
diff --git a/src/uuid.rs b/src/uuid.rs
index a62f191..b12bd6a 100644
--- a/src/uuid.rs
+++ b/src/uuid.rs
@@ -13,7 +13,7 @@ impl Julid {
/// means that some bits in the original Julid are overwritten with
/// UUID-specific values, but only six bits in total are potentially
/// altered.
- pub fn as_uuid(&self) -> Uuid {
+ pub const fn as_uuid(&self) -> Uuid {
let counter_mask = (1 << 12) - 1;
let entropy_mask = (1 << 62) - 1;
let timestamp = self.timestamp();
@@ -29,7 +29,9 @@ impl Julid {
///
/// 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.
- /// 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 {
let ver = id.get_version_num();
if ver != 7 {
@@ -107,6 +109,7 @@ mod test {
assert_eq!(j1.timestamp(), ju1.timestamp());
assert_eq!(j1.counter(), ju1.counter());
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
// point
let u2 = ju1.as_uuid();