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}