tick_id/
lib.rs

1/*----------------------------------------------------------------------------------------------------------
2 *  Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/tick-id-rs
3 *  Licensed under the MIT License. See LICENSE in the project root for license information.
4 *--------------------------------------------------------------------------------------------------------*/
5//! The `TickId` type represents a specific tick in a deterministic simulation.
6//!
7//! A tick typically corresponds to a duration of 16 ms or 32 ms, but it can denote any positive integer time
8//! period, excluding zero. The `TickId` is implemented as a `u32`, allowing for a wide range of tick values.
9//!
10//! ## Example
11//!
12//! ```
13//! use tick_id::TickId;
14//!
15//! let tick_id = TickId::new(1);
16//! println!("Tick ID: {}", tick_id);
17//! ```
18//!
19//! ## Operations
20//!
21//! The `TickId` type supports addition and subtraction operations, allowing for easy manipulation of tick values.
22//! Overflow and underflow are checked during arithmetic operations to ensure safety.
23
24use core::fmt;
25use std::ops::{Add, AddAssign, Sub, SubAssign};
26
27/// A unique identifier for a specific tick in a deterministic simulation.
28#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
29pub struct TickId(pub u32);
30
31impl fmt::Display for TickId {
32    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33        write!(f, "tick:{:08X}", self.0)
34    }
35}
36
37impl TickId {
38    /// Creates a new `TickId` with the specified value.
39    ///
40    /// # Arguments
41    ///
42    /// * `value` - The underlying `u32` value for the `TickId`.
43    ///
44    /// # Examples
45    ///
46    /// ```
47    /// use tick_id::TickId;
48    ///
49    /// let tick_id = TickId::new(1);
50    /// assert_eq!(tick_id.value(), 1);
51    /// ```
52    pub fn new(value: u32) -> Self {
53        TickId(value)
54    }
55
56    /// Returns the underlying `u32` value of the `TickId`.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use tick_id::TickId;
62    ///
63    /// let tick_id = TickId::new(1);
64    /// assert_eq!(tick_id.value(), 1);
65    /// ```
66    pub fn value(&self) -> u32 {
67        self.0
68    }
69}
70
71impl Add<u32> for TickId {
72    type Output = TickId;
73
74    /// Adds a `u32` value to the `TickId`.
75    ///
76    /// # Panics
77    ///
78    /// This method will panic if the addition results in an overflow.
79    fn add(self, other: u32) -> TickId {
80        if self.0.checked_add(other).is_none() {
81            panic!("tick overflow. tried to do {} + {}", self.0, other)
82        }
83        TickId(self.0 + other)
84    }
85}
86
87impl AddAssign<u32> for TickId {
88    /// Adds a `u32` value to the `TickId` in place.
89    fn add_assign(&mut self, other: u32) {
90        self.0 += other;
91    }
92}
93
94impl Sub<u32> for TickId {
95    type Output = TickId;
96
97    /// Subtracts a `u32` value from the `TickId`.
98    ///
99    /// # Panics
100    ///
101    /// This method will panic if the subtraction results in an underflow.
102    fn sub(self, other: u32) -> TickId {
103        if other > self.0 {
104            panic!("tick underflow. tried to do {} - {}", self.0, other)
105        }
106        Self(self.0 - other)
107    }
108}
109
110impl SubAssign<u32> for TickId {
111    /// Subtracts a `u32` value from the `TickId` in place.
112    fn sub_assign(&mut self, other: u32) {
113        self.0 -= other;
114    }
115}
116
117impl Sub<TickId> for TickId {
118    type Output = i64;
119
120    /// Calculates the difference between two `TickId` values.
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// use tick_id::TickId;
126    ///
127    /// let tick_id1 = TickId::new(10);
128    /// let tick_id2 = TickId::new(5);
129    /// assert_eq!(tick_id1 - tick_id2, 5);
130    /// ```
131    fn sub(self, other: TickId) -> i64 {
132        (self.0 as i64) - (other.0 as i64)
133    }
134}