1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Low level time utilities.
use crate::{
    core::optional::{gen_optional, NSTDOptional},
    NSTDFloat64, NSTDInt64, NSTDUInt32,
};
use core::time::Duration;
use nstdapi::nstdapi;

/// Represents a span of time.
#[nstdapi]
#[derive(Clone, Copy, PartialEq)]
pub struct NSTDDuration {
    /// The duration in seconds.
    seconds: NSTDFloat64,
}
impl NSTDDuration {
    /// Converts an [`NSTDDuration`] into a [Duration].
    ///
    /// # Panics
    ///
    /// Panics if `duration` is negative, overflows Rust's `Duration` structure, or is non-finite.
    #[inline]
    #[allow(dead_code)]
    pub(crate) fn into_duration(self) -> Duration {
        Duration::from_secs_f64(self.seconds)
    }
}
gen_optional!(NSTDOptionalDuration, NSTDDuration);

/// Creates a new `NSTDDuration` object from an `NSTDFloat64` representing the duration in seconds.
///
/// # Parameters:
///
/// - `NSTDFloat64 seconds` - The time span in seconds.
///
/// # Returns
///
/// `NSTDDuration duration` - The time span represented as an `NSTDDuration` object.
#[inline]
#[nstdapi]
pub const fn nstd_core_time_duration_new(seconds: NSTDFloat64) -> NSTDDuration {
    NSTDDuration { seconds }
}

/// Returns the number of seconds stored in an `NSTDDuration` as an `NSTDFloat64`.
///
/// # Parameters:
///
/// - `NSTDDuration duration` - The duration object.
///
/// # Returns
///
/// `NSTDFloat64 seconds` - The number of seconds in a duration object represented as an
/// `NSTDFloat64`.
#[inline]
#[nstdapi]
pub const fn nstd_core_time_duration_get(duration: NSTDDuration) -> NSTDFloat64 {
    duration.seconds
}

/// Returns the number of seconds in an `NSTDDuration` object.
///
/// # Parameters:
///
/// - `NSTDDuration duration` - The duration object.
///
/// # Returns
///
/// `NSTDInt64 seconds` - The number of seconds held in `duration`.
#[inline]
#[nstdapi]
#[allow(clippy::cast_possible_truncation)]
pub const fn nstd_core_time_duration_seconds(duration: NSTDDuration) -> NSTDInt64 {
    duration.seconds as _
}

/// Returns the number of nanoseconds in an `NSTDDuration` object.
///
/// # Parameters:
///
/// - `NSTDDuration duration` - The duration object.
///
/// # Returns
///
/// `NSTDUInt32 nanoseconds` - The number of nanoseconds held in `duration`.
#[nstdapi]
pub fn nstd_core_time_duration_nanoseconds(duration: NSTDDuration) -> NSTDUInt32 {
    /// The number of nanoseconds in a full second.
    const NANOS_IN_SEC: NSTDFloat64 = 1_000_000_000.0;
    #[allow(
        clippy::cast_possible_truncation,
        clippy::cast_precision_loss,
        clippy::cast_sign_loss
    )]
    {
        let nanos = duration.seconds - duration.seconds as NSTDInt64 as NSTDFloat64;
        match nanos >= 0.0 {
            true => (nanos * NANOS_IN_SEC) as _,
            false => (nanos * -NANOS_IN_SEC) as _,
        }
    }
}

/// Computes the addition of two time spans.
///
/// # Parameters:
///
/// - `NSTDDuration lhs` - The left-hand side operand.
///
/// - `NSTDDuration rhs` - The right-hand side operand.
///
/// # Returns
///
/// `NSTDDuration duration` - The result of the time span addition.
#[inline]
#[nstdapi]
pub fn nstd_core_time_duration_add(lhs: NSTDDuration, rhs: NSTDDuration) -> NSTDDuration {
    nstd_core_time_duration_new(lhs.seconds + rhs.seconds)
}

/// Computes the subtraction between two time spans.
///
/// # Parameters:
///
/// - `NSTDDuration lhs` - The left-hand side operand.
///
/// - `NSTDDuration rhs` - The right-hand side operand.
///
/// # Returns
///
/// `NSTDDuration duration` - The result of the time span subtraction.
#[inline]
#[nstdapi]
pub fn nstd_core_time_duration_sub(lhs: NSTDDuration, rhs: NSTDDuration) -> NSTDDuration {
    nstd_core_time_duration_new(lhs.seconds - rhs.seconds)
}