use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct NodeId(pub u64);
impl NodeId {
pub const INVALID: Self = Self(u64::MAX);
#[inline]
#[must_use]
pub const fn new(id: u64) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u64(&self) -> u64 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u64::MAX
}
}
impl fmt::Debug for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "NodeId({})", self.0)
} else {
write!(f, "NodeId(INVALID)")
}
}
}
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for NodeId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<NodeId> for u64 {
fn from(id: NodeId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct EdgeId(pub u64);
impl EdgeId {
pub const INVALID: Self = Self(u64::MAX);
#[inline]
#[must_use]
pub const fn new(id: u64) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u64(&self) -> u64 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u64::MAX
}
}
impl fmt::Debug for EdgeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "EdgeId({})", self.0)
} else {
write!(f, "EdgeId(INVALID)")
}
}
}
impl fmt::Display for EdgeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for EdgeId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<EdgeId> for u64 {
fn from(id: EdgeId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct TransactionId(pub u64);
impl TransactionId {
pub const INVALID: Self = Self(u64::MAX);
pub const SYSTEM: Self = Self(1);
#[inline]
#[must_use]
pub const fn new(id: u64) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u64(&self) -> u64 {
self.0
}
#[inline]
#[must_use]
pub const fn next(&self) -> Self {
Self(self.0 + 1)
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u64::MAX
}
}
impl fmt::Debug for TransactionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "TransactionId({})", self.0)
} else {
write!(f, "TransactionId(INVALID)")
}
}
}
impl fmt::Display for TransactionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for TransactionId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<TransactionId> for u64 {
fn from(id: TransactionId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct EpochId(pub u64);
impl EpochId {
pub const INITIAL: Self = Self(0);
pub const PENDING: Self = Self(u64::MAX);
#[inline]
#[must_use]
pub const fn new(id: u64) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u64(&self) -> u64 {
self.0
}
#[inline]
#[must_use]
pub const fn next(&self) -> Self {
Self(self.0 + 1)
}
#[inline]
#[must_use]
pub const fn is_visible_at(&self, viewing_epoch: Self) -> bool {
self.0 <= viewing_epoch.0
}
}
impl fmt::Debug for EpochId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "EpochId({})", self.0)
}
}
impl fmt::Display for EpochId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for EpochId {
fn from(id: u64) -> Self {
Self(id)
}
}
impl From<EpochId> for u64 {
fn from(id: EpochId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct LabelId(pub u32);
impl LabelId {
pub const INVALID: Self = Self(u32::MAX);
#[inline]
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u32(&self) -> u32 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u32::MAX
}
}
impl fmt::Debug for LabelId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "LabelId({})", self.0)
} else {
write!(f, "LabelId(INVALID)")
}
}
}
impl fmt::Display for LabelId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u32> for LabelId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl From<LabelId> for u32 {
fn from(id: LabelId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct PropertyKeyId(pub u32);
impl PropertyKeyId {
pub const INVALID: Self = Self(u32::MAX);
#[inline]
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u32(&self) -> u32 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u32::MAX
}
}
impl fmt::Debug for PropertyKeyId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "PropertyKeyId({})", self.0)
} else {
write!(f, "PropertyKeyId(INVALID)")
}
}
}
impl fmt::Display for PropertyKeyId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u32> for PropertyKeyId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl From<PropertyKeyId> for u32 {
fn from(id: PropertyKeyId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct EdgeTypeId(pub u32);
impl EdgeTypeId {
pub const INVALID: Self = Self(u32::MAX);
#[inline]
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u32(&self) -> u32 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u32::MAX
}
}
impl fmt::Debug for EdgeTypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "EdgeTypeId({})", self.0)
} else {
write!(f, "EdgeTypeId(INVALID)")
}
}
}
impl fmt::Display for EdgeTypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u32> for EdgeTypeId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl From<EdgeTypeId> for u32 {
fn from(id: EdgeTypeId) -> Self {
id.0
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default)]
#[repr(transparent)]
pub struct IndexId(pub u32);
impl IndexId {
pub const INVALID: Self = Self(u32::MAX);
#[inline]
#[must_use]
pub const fn new(id: u32) -> Self {
Self(id)
}
#[inline]
#[must_use]
pub const fn as_u32(&self) -> u32 {
self.0
}
#[inline]
#[must_use]
pub const fn is_valid(&self) -> bool {
self.0 != u32::MAX
}
}
impl fmt::Debug for IndexId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_valid() {
write!(f, "IndexId({})", self.0)
} else {
write!(f, "IndexId(INVALID)")
}
}
}
impl fmt::Display for IndexId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u32> for IndexId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl From<IndexId> for u32 {
fn from(id: IndexId) -> Self {
id.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_id_basic() {
let id = NodeId::new(42);
assert_eq!(id.as_u64(), 42);
assert!(id.is_valid());
assert!(!NodeId::INVALID.is_valid());
}
#[test]
fn test_node_id_ordering() {
let id1 = NodeId::new(1);
let id2 = NodeId::new(2);
assert!(id1 < id2);
}
#[test]
fn test_edge_id_basic() {
let id = EdgeId::new(100);
assert_eq!(id.as_u64(), 100);
assert!(id.is_valid());
assert!(!EdgeId::INVALID.is_valid());
}
#[test]
fn test_tx_id_basic() {
let id = TransactionId::new(1);
assert!(id.is_valid());
assert!(!TransactionId::INVALID.is_valid());
assert_eq!(id.next(), TransactionId::new(2));
}
#[test]
fn test_epoch_visibility() {
let e1 = EpochId::new(1);
let e2 = EpochId::new(2);
let e3 = EpochId::new(3);
assert!(e1.is_visible_at(e2));
assert!(e1.is_visible_at(e3));
assert!(!e2.is_visible_at(e1));
assert!(e2.is_visible_at(e2));
assert!(e2.is_visible_at(e3));
assert!(!e3.is_visible_at(e1));
assert!(!e3.is_visible_at(e2));
assert!(e3.is_visible_at(e3));
}
#[test]
fn test_epoch_next() {
let e = EpochId::INITIAL;
assert_eq!(e.next(), EpochId::new(1));
assert_eq!(e.next().next(), EpochId::new(2));
}
#[test]
fn test_conversions() {
let node_id: NodeId = 42u64.into();
let raw: u64 = node_id.into();
assert_eq!(raw, 42);
let edge_id: EdgeId = 100u64.into();
let raw: u64 = edge_id.into();
assert_eq!(raw, 100);
let tx_id: TransactionId = 1u64.into();
let raw: u64 = tx_id.into();
assert_eq!(raw, 1);
let epoch_id: EpochId = 5u64.into();
let raw: u64 = epoch_id.into();
assert_eq!(raw, 5);
}
}