Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_datime/src/clock/millisecond.rs

3.6 KiB, 21 runs

created by r1870400018:6323, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\
2//! Anthropic Claude
3
4use crate::clock::{
5 PerSecondRated,
6 ClockNanoSecond,
7};
8
9use oxedyne_fe2o3_core::prelude::*;
10
11use std::fmt;
12
13/// A millisecond face over ClockNanoSecond: the arithmetic happens in
14/// nanoseconds and is converted back on the way out.
15///
16/// ```ignore
17/// use oxedyne_fe2o3_datime::clock::ClockMilliSecondres!();
18///
19/// let millis = ClockMilliSecond::new(500)?res!();
20/// assert_eq!(millis.of(), 500)res!();
21/// assert_eq!(millis.as_nanos().of(), 500_000_000)res!();
22/// ```
23#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
24pub struct ClockMilliSecond {
25 nanos: ClockNanoSecond,
26}
27
28impl ClockMilliSecond {
29 pub const MAX_VALUE: u32 = 999;
30 pub const NANOS_PER_MILLI: u32 = 1_000_000;
31
32 pub fn new(millis: u32) -> Outcome<Self> {
33 if millis > Self::MAX_VALUE {
34 return Err(err!(
35 "Millisecond {} is invalid, must be 0-{}",
36 millis,
37 Self::MAX_VALUE;
38 Invalid, Input
39 ));
40 }
41 let nanos = res!(ClockNanoSecond::from_millis(millis));
42 Ok(Self { nanos })
43 }
44
45 pub(crate) fn new_unchecked(millis: u32) -> Self {
46 let nanos = ClockNanoSecond::new_unchecked(millis * Self::NANOS_PER_MILLI);
47 Self { nanos }
48 }
49
50 pub fn of(&self) -> u32 {
51 self.nanos.to_millis()
52 }
53
54 pub fn as_nanos(&self) -> ClockNanoSecond {
55 self.nanos
56 }
57
58 /// Truncates the sub-millisecond part.
59 pub fn from_nanos(nanos: ClockNanoSecond) -> Self {
60 let millis = nanos.to_millis();
61 Self::new_unchecked(millis)
62 }
63
64 pub fn add_millis(&self, millis: u32) -> (Self, u32) {
65 let nanos_to_add = millis as u64 * Self::NANOS_PER_MILLI as u64;
66 let (new_nanos, second_carry) = self.nanos.add_nanos(nanos_to_add);
67 (Self::from_nanos(new_nanos), second_carry)
68 }
69
70 pub fn sub_millis(&self, millis: u32) -> (Self, u32) {
71 let nanos_to_sub = millis as u64 * Self::NANOS_PER_MILLI as u64;
72 let (new_nanos, second_borrow) = self.nanos.sub_nanos(nanos_to_sub);
73 (Self::from_nanos(new_nanos), second_borrow)
74 }
75}
76
77// Validation methods.
78impl ClockMilliSecond {
79 pub fn is_valid(&self) -> bool {
80 self.of() <= Self::MAX_VALUE
81 }
82}
83
84impl PerSecondRated for ClockMilliSecond {
85 fn per_second(&self) -> u64 {
86 1_000
87 }
88}
89
90impl fmt::Display for ClockMilliSecond {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 write!(f, "{:03}", self.of())
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_millisecond_creation() {
102 assert!(ClockMilliSecond::new(0).is_ok());
103 assert!(ClockMilliSecond::new(500).is_ok());
104 assert!(ClockMilliSecond::new(999).is_ok());
105 assert!(ClockMilliSecond::new(1000).is_err());
106 }
107
108 #[test]
109 fn test_millisecond_conversions() {
110 let millis = ClockMilliSecond::new(123).unwrap();
111 assert_eq!(millis.of(), 123);
112 assert_eq!(millis.as_nanos().of(), 123_000_000);
113
114 let nanos = ClockNanoSecond::new(123_456_789).unwrap();
115 let millis = ClockMilliSecond::from_nanos(nanos);
116 assert_eq!(millis.of(), 123); // truncated
117 }
118
119 #[test]
120 fn test_millisecond_arithmetic() {
121 let millis = ClockMilliSecond::new(500).unwrap();
122 let (new_millis, carry) = millis.add_millis(300);
123 assert_eq!(new_millis.of(), 800);
124 assert_eq!(carry, 0);
125
126 let (new_millis, carry) = millis.add_millis(700);
127 assert_eq!(new_millis.of(), 200);
128 assert_eq!(carry, 1);
129
130 let (new_millis, borrow) = millis.sub_millis(200);
131 assert_eq!(new_millis.of(), 300);
132 assert_eq!(borrow, 0);
133
134 let (new_millis, borrow) = millis.sub_millis(700);
135 assert_eq!(new_millis.of(), 800);
136 assert_eq!(borrow, 1);
137 }
138
139 #[test]
140 fn test_per_second_rated() {
141 let millis = ClockMilliSecond::new(456).unwrap();
142 assert_eq!(millis.per_second(), 1_000);
143 }
144}