Oregami
Repositories/oxedyne/fe2o3

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

4.0 KiB, 23 runs

created by r1870400018:6329, 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::PerSecondRated;
5
6use oxedyne_fe2o3_core::prelude::*;
7
8use std::fmt;
9
10/// 0 to 999,999,999, the finest resolution the clock types carry.
11///
12/// ```ignore
13/// use oxedyne_fe2o3_datime::clock::ClockNanoSecondres!();
14///
15/// let nanos = ClockNanoSecond::from_millis(500)?res!();
16/// assert_eq!(nanos.of(), 500_000_000)res!();
17/// assert_eq!(nanos.to_millis(), 500)res!();
18/// ```
19#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
20pub struct ClockNanoSecond {
21 value: u32,
22}
23
24impl ClockNanoSecond {
25 pub const MAX_VALUE: u32 = 999_999_999;
26 pub const NANOS_PER_SECOND: u32 = 1_000_000_000;
27
28 pub fn new(nanosecond: u32) -> Outcome<Self> {
29 if nanosecond > Self::MAX_VALUE {
30 return Err(err!(
31 "Nanosecond {} is invalid, must be 0-{}",
32 nanosecond,
33 Self::MAX_VALUE;
34 Invalid, Input
35 ));
36 }
37 Ok(Self { value: nanosecond })
38 }
39
40 pub(crate) fn new_unchecked(nanosecond: u32) -> Self {
41 Self { value: nanosecond }
42 }
43
44 pub fn of(&self) -> u32 {
45 self.value
46 }
47
48 pub fn from_millis(millis: u32) -> Outcome<Self> {
49 let nanos = res!(millis.checked_mul(1_000_000)
50 .ok_or_else(|| err!("Millisecond overflow"; Overflow)));
51 Self::new(nanos)
52 }
53
54 pub fn from_micros(micros: u32) -> Outcome<Self> {
55 let nanos = res!(micros.checked_mul(1_000)
56 .ok_or_else(|| err!("Microsecond overflow"; Overflow)));
57 Self::new(nanos)
58 }
59
60 /// Truncates.
61 pub fn to_millis(&self) -> u32 {
62 self.value / 1_000_000
63 }
64
65 pub fn to_micros(&self) -> u32 {
66 self.value / 1_000
67 }
68
69 pub fn add_nanos(&self, nanos: u64) -> (Self, u32) {
70 let total = self.value as u64 + nanos;
71 let second_carry = (total / Self::NANOS_PER_SECOND as u64) as u32;
72 let new_nano = (total % Self::NANOS_PER_SECOND as u64) as u32;
73 (Self::new_unchecked(new_nano), second_carry)
74 }
75
76 pub fn sub_nanos(&self, nanos: u64) -> (Self, u32) {
77 if nanos as u32 > self.value {
78 let borrow_needed = ((nanos as u32 - self.value + Self::NANOS_PER_SECOND - 1) / Self::NANOS_PER_SECOND) as u32;
79 let effective_nanos = borrow_needed as u64 * Self::NANOS_PER_SECOND as u64 + self.value as u64 - nanos;
80 (Self::new_unchecked(effective_nanos as u32), borrow_needed)
81 } else {
82 (Self::new_unchecked(self.value - nanos as u32), 0)
83 }
84 }
85}
86
87// Validation methods.
88impl ClockNanoSecond {
89 pub fn is_valid(&self) -> bool {
90 self.value <= Self::MAX_VALUE
91 }
92}
93
94impl PerSecondRated for ClockNanoSecond {
95 fn per_second(&self) -> u64 {
96 Self::NANOS_PER_SECOND as u64
97 }
98}
99
100impl fmt::Display for ClockNanoSecond {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "{:09}", self.value)
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_nanosecond_creation() {
112 assert!(ClockNanoSecond::new(0).is_ok());
113 assert!(ClockNanoSecond::new(500_000_000).is_ok());
114 assert!(ClockNanoSecond::new(999_999_999).is_ok());
115 assert!(ClockNanoSecond::new(1_000_000_000).is_err());
116 }
117
118 #[test]
119 fn test_conversions() {
120 let nanos = ClockNanoSecond::from_millis(500).unwrap();
121 assert_eq!(nanos.of(), 500_000_000);
122 assert_eq!(nanos.to_millis(), 500);
123
124 let nanos = ClockNanoSecond::from_micros(500_000).unwrap();
125 assert_eq!(nanos.of(), 500_000_000);
126 assert_eq!(nanos.to_micros(), 500_000);
127 }
128
129 #[test]
130 fn test_nanosecond_arithmetic() {
131 let nano = ClockNanoSecond::new(500_000_000).unwrap();
132 let (new_nano, carry) = nano.add_nanos(300_000_000);
133 assert_eq!(new_nano.of(), 800_000_000);
134 assert_eq!(carry, 0);
135
136 let (new_nano, carry) = nano.add_nanos(700_000_000);
137 assert_eq!(new_nano.of(), 200_000_000);
138 assert_eq!(carry, 1);
139
140 let (new_nano, borrow) = nano.sub_nanos(200_000_000);
141 assert_eq!(new_nano.of(), 300_000_000);
142 assert_eq!(borrow, 0);
143
144 let (new_nano, borrow) = nano.sub_nanos(700_000_000);
145 assert_eq!(new_nano.of(), 800_000_000);
146 assert_eq!(borrow, 1);
147 }
148
149 #[test]
150 fn test_per_second_rated() {
151 let nano = ClockNanoSecond::new(123_456_789).unwrap();
152 assert_eq!(nano.per_second(), 1_000_000_000);
153 }
154}