use serde::{Deserialize, Serialize};
use std::fmt;
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
#[serde(into = "DagPositionWire")]
pub struct DagPosition {
pub(crate) wall_ms: u64,
pub(crate) counter: u16,
pub(crate) depth: u32,
pub(crate) lane: u32,
pub(crate) sequence: u32,
}
#[derive(Serialize, Deserialize)]
struct DagPositionWire {
wall_ms: u64,
counter: u16,
depth: u32,
lane: u32,
sequence: u32,
}
impl From<DagPosition> for DagPositionWire {
fn from(pos: DagPosition) -> Self {
Self {
wall_ms: pos.wall_ms,
counter: pos.counter,
depth: pos.depth,
lane: pos.lane,
sequence: pos.sequence,
}
}
}
impl From<DagPositionWire> for DagPosition {
fn from(wire: DagPositionWire) -> Self {
Self::with_hlc(
wire.wall_ms,
wire.counter,
wire.depth,
wire.lane,
wire.sequence,
)
}
}
impl<'de> Deserialize<'de> for DagPosition {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
DagPositionWire::deserialize(deserializer).map(DagPosition::from)
}
}
impl DagPosition {
pub const fn new(depth: u32, lane: u32, sequence: u32) -> Self {
Self {
wall_ms: 0,
counter: 0,
depth,
lane,
sequence,
}
}
pub const fn with_hlc(
wall_ms: u64,
counter: u16,
depth: u32,
lane: u32,
sequence: u32,
) -> Self {
Self {
wall_ms,
counter,
depth,
lane,
sequence,
}
}
pub const fn root() -> Self {
Self {
wall_ms: 0,
counter: 0,
depth: 0,
lane: 0,
sequence: 0,
}
}
pub const fn child(sequence: u32) -> Self {
Self {
wall_ms: 0,
counter: 0,
depth: 0,
lane: 0,
sequence,
}
}
pub const fn child_at(sequence: u32, wall_ms: u64, counter: u16) -> Self {
Self {
wall_ms,
counter,
depth: 0,
lane: 0,
sequence,
}
}
pub const fn fork(parent_depth: u32, new_lane: u32) -> Self {
Self {
wall_ms: 0,
counter: 0,
depth: parent_depth + 1,
lane: new_lane,
sequence: 0,
}
}
pub const fn wall_ms(&self) -> u64 {
self.wall_ms
}
pub const fn counter(&self) -> u16 {
self.counter
}
pub const fn depth(&self) -> u32 {
self.depth
}
pub const fn lane(&self) -> u32 {
self.lane
}
pub const fn sequence(&self) -> u32 {
self.sequence
}
pub const fn is_root(&self) -> bool {
self.depth == 0 && self.lane == 0 && self.sequence == 0
}
pub const fn is_ancestor_of(&self, other: &DagPosition) -> bool {
self.lane == other.lane && self.depth == other.depth && self.sequence < other.sequence
}
}
impl fmt::Display for DagPosition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}:{}:{}@{}.{}",
self.depth, self.lane, self.sequence, self.wall_ms, self.counter
)
}
}
impl PartialOrd for DagPosition {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.lane != other.lane || self.depth != other.depth {
return None; }
let sequence_order = self.sequence.cmp(&other.sequence);
if sequence_order != std::cmp::Ordering::Equal {
return Some(sequence_order);
}
if self.wall_ms == other.wall_ms && self.counter == other.counter {
return Some(std::cmp::Ordering::Equal);
}
None
}
}