use std::fmt;
use crate::state::Id;
macro_rules! define_id {
(
$(#[$outer:meta])*
$name:ident
) => {
$(#[$outer])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct $name(u64);
impl $name {
pub const fn from_u64(value: u64) -> Self {
Self(value)
}
pub const fn as_u64(self) -> u64 {
self.0
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for $name {
fn from(value: u64) -> Self {
Self::from_u64(value)
}
}
impl From<$name> for u64 {
fn from(id: $name) -> u64 {
id.as_u64()
}
}
impl Id for $name {
fn as_u64(self) -> u64 {
self.as_u64()
}
fn from_u64(value: u64) -> Self {
Self::from_u64(value)
}
}
};
}
define_id! {
TableId
}
define_id! {
RowId
}
define_id! {
ColumnId
}
define_id! {
PartitionId
}
define_id! {
TransactionId
}
define_id! {
ReducerId
}
define_id! {
SubscriptionId
}
define_id! {
WorldId
}
define_id! {
WorkerId
}
define_id! {
SystemId
}
define_id! {
TickId
}
define_id! {
ConnectionId
}
define_id! {
SessionId
}
define_id! {
GameInstanceId
}
define_id! {
PlayerId
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
fn assert_id<I: Id>(id: I, raw: u64) {
assert_eq!(id.as_u64(), raw);
assert_eq!(I::from_u64(raw), id);
}
#[test]
fn roundtrip_raw_value() {
assert_id(TableId::from_u64(7), 7);
assert_id(RowId::from_u64(42), 42);
assert_id(ColumnId::from_u64(1), 1);
assert_id(PartitionId::from_u64(0), 0);
assert_id(TransactionId::from_u64(99), 99);
assert_id(ReducerId::from_u64(3), 3);
assert_id(SubscriptionId::from_u64(12), 12);
assert_id(WorldId::from_u64(1), 1);
assert_id(WorkerId::from_u64(2), 2);
assert_id(SystemId::from_u64(4), 4);
assert_id(TickId::from_u64(17), 17);
assert_id(ConnectionId::from_u64(9), 9);
assert_id(SessionId::from_u64(11), 11);
assert_id(GameInstanceId::from_u64(5), 5);
assert_id(PlayerId::from_u64(6), 6);
}
#[test]
fn converts_via_from() {
let id: TableId = 7u64.into();
let raw: u64 = id.into();
assert_eq!(raw, 7);
assert_eq!(id, TableId::from_u64(7));
}
#[test]
fn displays_as_raw_number() {
assert_eq!(TableId::from_u64(7).to_string(), "7");
assert_eq!(RowId::from_u64(42).to_string(), "42");
}
#[test]
fn ordering_and_hash_usable_in_maps() {
let mut map = HashMap::new();
map.insert(RowId::from_u64(1), "first");
map.insert(RowId::from_u64(2), "second");
assert_eq!(map[&RowId::from_u64(2)], "second");
assert!(RowId::from_u64(1) < RowId::from_u64(2));
}
#[test]
fn ids_are_distinct_types_with_matching_raw_values() {
assert_eq!(TableId::from_u64(1).as_u64(), RowId::from_u64(1).as_u64());
}
}