use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use uuid::Uuid;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct NodeId(pub u64);
impl NodeId {
pub fn new() -> Self {
Self(rand_u64())
}
pub const fn from_raw(value: u64) -> Self {
Self(value)
}
pub const fn as_u64(&self) -> u64 {
self.0
}
}
impl Default for NodeId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NodeId({:016x})", self.0)
}
}
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:016x}", self.0)
}
}
impl FromStr for NodeId {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
u64::from_str_radix(s, 16).map(NodeId)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TaskId(pub Uuid);
impl TaskId {
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub const fn from_uuid(uuid: Uuid) -> Self {
Self(uuid)
}
pub const fn as_uuid(&self) -> &Uuid {
&self.0
}
pub fn parse(s: &str) -> Result<Self, uuid::Error> {
Ok(Self(Uuid::parse_str(s)?))
}
}
impl Default for TaskId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for TaskId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TaskId({})", self.0)
}
}
impl fmt::Display for TaskId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct InstanceId(pub Uuid);
impl InstanceId {
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub const fn from_uuid(uuid: Uuid) -> Self {
Self(uuid)
}
pub const fn as_uuid(&self) -> &Uuid {
&self.0
}
pub fn parse(s: &str) -> Result<Self, uuid::Error> {
Ok(Self(Uuid::parse_str(s)?))
}
}
impl Default for InstanceId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for InstanceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "InstanceId({})", self.0)
}
}
impl fmt::Display for InstanceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
fn rand_u64() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
use std::cell::Cell;
thread_local! {
static STATE: Cell<u64> = Cell::new(
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64
);
}
STATE.with(|state| {
let mut x = state.get();
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
state.set(x);
x
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_id_unique() {
let id1 = NodeId::new();
let id2 = NodeId::new();
assert_ne!(id1, id2);
}
#[test]
fn test_task_id_parse() {
let id = TaskId::new();
let parsed = TaskId::parse(&id.to_string()).unwrap();
assert_eq!(id, parsed);
}
#[test]
fn test_instance_id_ordered() {
let id1 = InstanceId::new();
std::thread::sleep(std::time::Duration::from_millis(1));
let id2 = InstanceId::new();
assert!(id1.0 < id2.0);
}
}