nautilus_core/interval.rs
1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Closed interval types shared across request planning and persistence coverage.
17
18/// A closed nanosecond interval, inclusive at both ends.
19#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub struct ClosedInterval {
21 /// Inclusive start in nanoseconds since the Unix epoch.
22 pub start: u64,
23 /// Inclusive end in nanoseconds since the Unix epoch.
24 pub end: u64,
25}
26
27impl ClosedInterval {
28 /// Creates a closed interval if `start <= end`.
29 #[must_use]
30 pub const fn new(start: u64, end: u64) -> Option<Self> {
31 if start <= end {
32 Some(Self { start, end })
33 } else {
34 None
35 }
36 }
37}
38
39impl From<ClosedInterval> for (u64, u64) {
40 fn from(interval: ClosedInterval) -> Self {
41 (interval.start, interval.end)
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use rstest::rstest;
48
49 use super::*;
50
51 #[rstest]
52 #[case(0, 0, true)]
53 #[case(0, 1, true)]
54 #[case(2, 1, false)]
55 fn test_new_validates_order(#[case] start: u64, #[case] end: u64, #[case] expected: bool) {
56 assert_eq!(ClosedInterval::new(start, end).is_some(), expected);
57 }
58
59 #[rstest]
60 fn test_new_stores_bounds() {
61 let interval = ClosedInterval::new(3, 7).unwrap();
62 assert_eq!((interval.start, interval.end), (3, 7));
63 }
64
65 #[rstest]
66 fn test_into_tuple() {
67 let interval = ClosedInterval::new(3, 7).unwrap();
68 let pair: (u64, u64) = interval.into();
69 assert_eq!(pair, (3, 7));
70 }
71}