sbrd_gen/generator/primitive/
time_generator.rs1use crate::builder::{GeneratorBuilder, ValueBound};
2use crate::error::{BuildError, GenerateError};
3use crate::eval::Evaluator;
4use crate::generator::{GeneratorBase, Randomizer};
5use crate::value::{DataValue, DataValueMap, SbrdTime, TIME_DEFAULT_FORMAT};
6use crate::GeneratorType;
7use chrono::Duration;
8use std::ops::AddAssign;
9
10#[derive(Debug, PartialEq, Clone)]
20pub struct TimeGenerator {
21 nullable: bool,
22 format: String,
23 range: ValueBound<SbrdTime>,
24}
25
26impl<R: Randomizer + ?Sized> GeneratorBase<R> for TimeGenerator {
27 fn create(builder: GeneratorBuilder) -> Result<Self, BuildError>
28 where
29 Self: Sized,
30 {
31 let GeneratorBuilder {
32 generator_type,
33 nullable,
34 range,
35 format,
36 ..
37 } = builder;
38
39 if generator_type != GeneratorType::Time {
40 return Err(BuildError::InvalidType(generator_type));
41 }
42
43 let default_range = Self::default_range();
44 let _range = match range {
45 None => default_range,
46 Some(r) => r
47 .try_convert_with(|s| {
48 SbrdTime::parse_from_str(&s.to_parse_string(), TIME_DEFAULT_FORMAT).map_err(
49 |e| {
50 BuildError::FailParseValue(
51 s.to_parse_string(),
52 "Time".to_string(),
53 e.to_string(),
54 )
55 },
56 )
57 })
58 .map(|range| {
59 range.without_no_bound_from_other(default_range)
61 })?,
62 };
63 if _range.is_empty() {
64 return Err(BuildError::RangeEmpty(_range.convert_into()));
65 }
66
67 Ok(Self {
68 nullable,
69 format: format.unwrap_or_else(|| TIME_DEFAULT_FORMAT.to_string()),
70 range: _range,
71 })
72 }
73
74 fn is_nullable(&self) -> bool {
75 self.nullable
76 }
77
78 fn generate_without_null(
79 &self,
80 rng: &mut R,
81 context: &DataValueMap<&str>,
82 ) -> Result<DataValue, GenerateError> {
83 let upper_bound = self
84 .range
85 .get_end()
86 .expect("Exist upper bound is not exist");
87 let lower_bound = self
88 .range
89 .get_start()
90 .expect("Exist lower bound is not exist");
91 let since_duration_seconds = upper_bound.signed_duration_since(lower_bound).num_seconds();
92 let diff_seconds = rng.gen_range(ValueBound::new(
93 Some(0),
94 Some((self.range.is_include_end(), since_duration_seconds)),
95 ));
96 let mut time_value = lower_bound;
97 time_value.add_assign(Duration::seconds(diff_seconds));
98
99 let evaluator = Evaluator::new(context);
100 let format = evaluator.format_script(&self.format).map_err(|e| {
101 GenerateError::FailEval(
102 e,
103 self.format.to_string(),
104 context
105 .clone()
106 .into_iter()
107 .map(|(k, v)| (k.to_string(), v))
108 .collect::<DataValueMap<String>>(),
109 )
110 })?;
111
112 Ok(DataValue::String(time_value.format(&format).to_string()))
113 }
114}
115
116impl TimeGenerator {
117 #[inline]
118 fn min_time() -> SbrdTime {
119 SbrdTime::from_hms(0, 0, 0)
120 }
121 #[inline]
122 fn max_time() -> SbrdTime {
123 SbrdTime::from_hms(23, 59, 59)
124 }
125
126 fn default_range() -> ValueBound<SbrdTime> {
127 ValueBound::new(Some(Self::min_time()), Some((true, Self::max_time())))
128 }
129}