re_log_types/index/
time_int.rs1use crate::{Duration, NonMinI64, TryFromIntError};
2
3#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub struct TimeInt(Option<NonMinI64>);
11
12static_assertions::assert_eq_size!(TimeInt, i64);
13static_assertions::assert_eq_align!(TimeInt, i64);
14
15impl re_byte_size::SizeBytes for TimeInt {
16 #[inline]
17 fn heap_size_bytes(&self) -> u64 {
18 0
19 }
20}
21
22impl std::fmt::Debug for TimeInt {
23 #[inline]
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 match self.0 {
26 Some(NonMinI64::MIN) => f
27 .debug_tuple("TimeInt::MIN")
28 .field(&NonMinI64::MIN)
29 .finish(),
30 Some(NonMinI64::MAX) => f
31 .debug_tuple("TimeInt::MAX")
32 .field(&NonMinI64::MAX)
33 .finish(),
34 Some(t) => f.write_fmt(format_args!("TimeInt({})", re_format::format_int(t.get()))),
35 None => f.debug_tuple("TimeInt::STATIC").finish(),
36 }
37 }
38}
39
40impl TimeInt {
41 pub const STATIC: Self = Self(None);
48
49 pub const MIN: Self = Self(Some(NonMinI64::MIN));
54
55 pub const MAX: Self = Self(Some(NonMinI64::MAX));
57
58 pub const ZERO: Self = Self(Some(NonMinI64::ZERO));
59
60 pub const ONE: Self = Self(Some(NonMinI64::ONE));
61
62 #[inline]
63 pub fn is_static(self) -> bool {
64 self == Self::STATIC
65 }
66
67 #[inline]
73 pub fn new_temporal(time: i64) -> Self {
74 NonMinI64::new(time).map_or(Self::MIN, |t| Self(Some(t)))
75 }
76
77 #[inline]
79 pub fn from_nanos(nanos: NonMinI64) -> Self {
80 Self(Some(nanos))
81 }
82
83 #[inline]
85 pub fn from_millis(millis: NonMinI64) -> Self {
86 Self::new_temporal(millis.get().saturating_mul(1_000_000))
87 }
88
89 #[inline]
91 pub fn from_secs(seconds: f64) -> Self {
92 Self::new_temporal((seconds * 1e9).round() as _)
93 }
94
95 #[inline]
97 pub fn from_sequence(sequence: NonMinI64) -> Self {
98 Self(Some(sequence))
99 }
100
101 #[inline]
103 pub fn saturated_temporal_i64(value: impl Into<i64>) -> Self {
104 Self(Some(NonMinI64::saturating_from_i64(value)))
105 }
106
107 #[inline]
109 pub fn saturated_temporal(value: impl TryInto<Self>) -> Self {
110 value.try_into().unwrap_or(Self::MIN).max(Self::MIN)
111 }
112
113 #[inline]
115 pub const fn as_i64(self) -> i64 {
116 match self.0 {
117 Some(t) => t.get(),
118 None => i64::MIN,
119 }
120 }
121
122 #[inline]
124 pub const fn as_f64(self) -> f64 {
125 match self.0 {
126 Some(t) => t.get() as _,
127 None => f64::MIN,
128 }
129 }
130
131 #[inline]
133 #[must_use]
134 pub fn inc(self) -> Self {
135 match self.0 {
136 Some(t) => Self::new_temporal(t.get().saturating_add(1)),
137 None => self,
138 }
139 }
140
141 #[inline]
143 #[must_use]
144 pub fn dec(self) -> Self {
145 match self.0 {
146 Some(t) => Self::new_temporal(t.get().saturating_sub(1)),
147 None => self,
148 }
149 }
150}
151
152impl TryFrom<i64> for TimeInt {
153 type Error = TryFromIntError;
154
155 #[inline]
156 fn try_from(t: i64) -> Result<Self, Self::Error> {
157 let Some(t) = NonMinI64::new(t) else {
158 return Err(TryFromIntError);
159 };
160 Ok(Self(Some(t)))
161 }
162}
163
164impl From<NonMinI64> for TimeInt {
165 #[inline]
166 fn from(seq: NonMinI64) -> Self {
167 Self(Some(seq))
168 }
169}
170
171impl From<TimeInt> for NonMinI64 {
172 fn from(value: TimeInt) -> Self {
173 match value.0 {
174 Some(value) => value,
175 None => Self::MIN,
176 }
177 }
178}
179
180impl From<TimeInt> for Duration {
191 #[inline]
192 fn from(int: TimeInt) -> Self {
193 Self::from_nanos(int.as_i64())
194 }
195}
196
197impl From<TimeInt> for re_types_core::datatypes::TimeInt {
198 #[inline]
199 fn from(time: TimeInt) -> Self {
200 Self(time.as_i64())
201 }
202}
203
204impl From<re_types_core::datatypes::TimeInt> for TimeInt {
205 #[inline]
206 fn from(time: re_types_core::datatypes::TimeInt) -> Self {
207 Self::new_temporal(time.0)
208 }
209}
210
211impl std::ops::Add for TimeInt {
212 type Output = Self;
213
214 #[inline]
215 fn add(self, rhs: Self) -> Self::Output {
216 match (self.0, rhs.0) {
217 (Some(lhs), Some(rhs)) => Self(Some(
219 NonMinI64::new(lhs.get().saturating_add(rhs.get())).unwrap_or(NonMinI64::MIN),
220 )),
221 _ => Self(None),
223 }
224 }
225}
226
227impl std::ops::Sub for TimeInt {
228 type Output = Self;
229
230 #[inline]
231 fn sub(self, rhs: Self) -> Self::Output {
232 match (self.0, rhs.0) {
233 (Some(lhs), Some(rhs)) => Self(Some(
235 NonMinI64::new(lhs.get().saturating_sub(rhs.get())).unwrap_or(NonMinI64::MIN),
236 )),
237 _ => Self(None),
239 }
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246
247 #[test]
248 fn saturated_temporal() {
249 assert_eq!(TimeInt::saturated_temporal_i64(i64::MIN), TimeInt::MIN);
250 assert_eq!(TimeInt::saturated_temporal_i64(i64::MIN + 1), TimeInt::MIN);
251 assert_eq!(TimeInt::saturated_temporal_i64(i64::MAX), TimeInt::MAX);
252 assert_eq!(
253 TimeInt::saturated_temporal_i64(i64::MAX - 1),
254 TimeInt::new_temporal(i64::MAX - 1)
255 );
256 }
257}