Skip to main content

forge/
run.rs

1#[cfg(test)]
2use googletest::{Result as GtestResult, prelude::*};
3
4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5pub(crate) struct IterationCount(u32);
6
7impl IterationCount {
8    pub(crate) const ONE: Self = Self(1);
9
10    #[must_use]
11    pub(crate) const fn get(self) -> u32 {
12        self.0
13    }
14}
15
16impl TryFrom<u32> for IterationCount {
17    type Error = RunParametersError;
18
19    fn try_from(value: u32) -> Result<Self, Self::Error> {
20        if value == 0 {
21            Err(RunParametersError::ZeroIterations)
22        } else {
23            Ok(Self(value))
24        }
25    }
26}
27
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29pub(crate) struct FightDurationSeconds(u32);
30
31impl FightDurationSeconds {
32    pub(crate) const fn from_nonzero_const(value: u32) -> Self {
33        assert!(value > 0, "fight duration must be nonzero");
34
35        Self(value)
36    }
37
38    #[must_use]
39    pub(crate) const fn get(self) -> u32 {
40        self.0
41    }
42}
43
44impl TryFrom<u32> for FightDurationSeconds {
45    type Error = RunParametersError;
46
47    fn try_from(value: u32) -> Result<Self, Self::Error> {
48        if value == 0 {
49            Err(RunParametersError::ZeroDuration)
50        } else {
51            Ok(Self(value))
52        }
53    }
54}
55
56#[derive(Clone, Copy, Debug, Eq, PartialEq)]
57pub(crate) struct RunParameters {
58    iterations: IterationCount,
59    fight_duration: FightDurationSeconds,
60}
61
62impl RunParameters {
63    #[must_use]
64    pub(crate) const fn new(
65        iterations: IterationCount,
66        fight_duration: FightDurationSeconds,
67    ) -> Self {
68        Self {
69            iterations,
70            fight_duration,
71        }
72    }
73
74    #[must_use]
75    pub(crate) const fn iterations(self) -> u32 {
76        self.iterations.get()
77    }
78
79    #[must_use]
80    pub(crate) const fn fight_duration_secs(self) -> u32 {
81        self.fight_duration.get()
82    }
83}
84
85#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
86pub(crate) enum RunParametersError {
87    #[error("iterations must be greater than zero")]
88    ZeroIterations,
89    #[error("duration must be greater than zero")]
90    ZeroDuration,
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[gtest]
98    fn validated_parameters_preserve_both_domains() -> GtestResult<()> {
99        let parameters = RunParameters::new(
100            IterationCount::try_from(17).or_fail()?,
101            FightDurationSeconds::try_from(45).or_fail()?,
102        );
103
104        verify_that!(parameters.iterations(), eq(17))?;
105        verify_that!(parameters.fight_duration_secs(), eq(45))?;
106
107        Ok(())
108    }
109
110    #[gtest]
111    fn zero_values_report_their_exact_domain() -> GtestResult<()> {
112        verify_that!(
113            IterationCount::try_from(0),
114            eq(Err(RunParametersError::ZeroIterations))
115        )?;
116        verify_that!(
117            FightDurationSeconds::try_from(0),
118            eq(Err(RunParametersError::ZeroDuration))
119        )?;
120        verify_that!(
121            RunParametersError::ZeroIterations.to_string(),
122            eq("iterations must be greater than zero")
123        )?;
124        verify_that!(
125            RunParametersError::ZeroDuration.to_string(),
126            eq("duration must be greater than zero")
127        )?;
128
129        Ok(())
130    }
131}