use crate::{ffi, mem};
pub fn uuid_v4() -> Option<String> {
uuid_with_version("v4")
}
pub fn uuid_v7() -> Option<String> {
uuid_with_version("v7")
}
fn uuid_with_version(version: &str) -> Option<String> {
let args = serde_json::json!({ "version": version });
let args_str = args.to_string();
let (args_ptr, args_len) = mem::host_arg_str(&args_str);
let result = unsafe { ffi::id_uuid(args_ptr, args_len) };
unsafe { mem::read_packed_string(result) }
}
pub fn ulid() -> Option<String> {
let result = unsafe { ffi::id_ulid() };
unsafe { mem::read_packed_string(result) }
}
pub fn nanoid(length: u32) -> Option<String> {
let result = unsafe { ffi::id_nanoid(length as i32) };
unsafe { mem::read_packed_string(result) }
}
pub fn ksuid() -> Option<String> {
let result = unsafe { ffi::id_ksuid() };
unsafe { mem::read_packed_string(result) }
}
pub fn snowflake() -> Option<String> {
let result = unsafe { ffi::snowflake_id() };
unsafe { mem::read_packed_string(result) }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ffi::test_host;
#[test]
fn uuid_v4_passes_version_in_args() {
test_host::reset();
test_host::with_mock(|m| {
m.id_uuid_response = Some("550e8400-e29b-41d4-a716-446655440000".into());
});
let id = uuid_v4().unwrap();
assert_eq!(id, "550e8400-e29b-41d4-a716-446655440000");
let captured = test_host::read_mock(|m| m.last_id_uuid_args.clone()).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&captured).unwrap();
assert_eq!(parsed["version"], "v4");
}
#[test]
fn uuid_v7_passes_version() {
test_host::reset();
test_host::with_mock(|m| {
m.id_uuid_response = Some("018e1234-5678-7abc-9def-0123456789ab".into());
});
uuid_v7().unwrap();
let captured = test_host::read_mock(|m| m.last_id_uuid_args.clone()).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&captured).unwrap();
assert_eq!(parsed["version"], "v7");
}
#[test]
fn uuid_none_when_host_silent() {
test_host::reset();
assert!(uuid_v4().is_none());
}
#[test]
fn ulid_returns_host_value() {
test_host::reset();
test_host::with_mock(|m| {
m.id_ulid_response = Some("01F8MECHZX3TBDSZ7XRADM79XE".into());
});
assert_eq!(ulid().as_deref(), Some("01F8MECHZX3TBDSZ7XRADM79XE"));
}
#[test]
fn nanoid_passes_length() {
test_host::reset();
test_host::with_mock(|m| {
m.id_nanoid_response = Some("V1StGXR8_Z5jdHi6B-myT".into());
});
let id = nanoid(21).unwrap();
assert_eq!(id.len(), 21);
assert_eq!(test_host::read_mock(|m| m.last_nanoid_length), Some(21));
}
#[test]
fn nanoid_zero_length_passes_zero() {
test_host::reset();
test_host::with_mock(|m| {
m.id_nanoid_response = Some("default".into());
});
nanoid(0).unwrap();
assert_eq!(test_host::read_mock(|m| m.last_nanoid_length), Some(0));
}
#[test]
fn ksuid_returns_host_value() {
test_host::reset();
test_host::with_mock(|m| {
m.id_ksuid_response = Some("0o5Fs0EELR0fUjHjbCnEtdUwQe3".into());
});
assert_eq!(ksuid().as_deref(), Some("0o5Fs0EELR0fUjHjbCnEtdUwQe3"));
}
#[test]
fn snowflake_returns_host_value() {
test_host::reset();
test_host::with_mock(|m| {
m.snowflake_id_response = Some("1234567890123456789".into());
});
assert_eq!(snowflake().as_deref(), Some("1234567890123456789"));
}
#[test]
fn snowflake_none_when_host_silent() {
test_host::reset();
assert!(snowflake().is_none());
}
}