Skip to main content

protify/validators/timestamp/
builder.rs

1#[doc(hidden)]
2pub mod state;
3use crate::validators::*;
4pub(crate) use state::*;
5
6use proto_types::{Duration, Timestamp};
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash)]
9pub struct TimestampValidatorBuilder<S: State = Empty> {
10	_state: PhantomData<S>,
11
12	data: TimestampValidator,
13}
14
15impl ProtoValidation for Timestamp {
16	#[doc(hidden)]
17	type Target = Self;
18	#[doc(hidden)]
19	type Stored = Self;
20	type Validator = TimestampValidator;
21	type ValidatorBuilder = TimestampValidatorBuilder;
22
23	#[doc(hidden)]
24	type UniqueStore<'a>
25		= CopyHybridStore<Self>
26	where
27		Self: 'a;
28
29	#[doc(hidden)]
30	const HAS_DEFAULT_VALIDATOR: bool = false;
31}
32impl<S: State> ValidatorBuilderFor<Timestamp> for TimestampValidatorBuilder<S> {
33	type Validator = TimestampValidator;
34	#[inline]
35	fn build_validator(self) -> TimestampValidator {
36		self.build()
37	}
38}
39
40impl<S: State> Default for TimestampValidatorBuilder<S> {
41	#[inline]
42	fn default() -> Self {
43		Self {
44			_state: PhantomData,
45			data: TimestampValidator::default(),
46		}
47	}
48}
49
50impl TimestampValidator {
51	#[must_use]
52	#[inline]
53	pub fn builder() -> TimestampValidatorBuilder {
54		TimestampValidatorBuilder::default()
55	}
56}
57
58impl<S: State> From<TimestampValidatorBuilder<S>> for ProtoOption {
59	#[inline(never)]
60	#[cold]
61	fn from(value: TimestampValidatorBuilder<S>) -> Self {
62		value.build().into()
63	}
64}
65
66#[allow(
67	clippy::must_use_candidate,
68	clippy::use_self,
69	clippy::return_self_not_must_use
70)]
71impl<S: State> TimestampValidatorBuilder<S> {
72	custom_error_messages_method!(Timestamp);
73
74	/// Adds a [`CelProgram`] to this validator.
75	#[inline]
76	pub fn cel(mut self, program: CelProgram) -> TimestampValidatorBuilder<S> {
77		self.data.cel.push(program);
78
79		TimestampValidatorBuilder {
80			_state: PhantomData,
81			..self
82		}
83	}
84
85	/// Specifies that this validator should always be ignored.
86	#[inline]
87	pub fn ignore_always(mut self) -> TimestampValidatorBuilder<SetIgnore<S>>
88	where
89		S::Ignore: IsUnset,
90	{
91		self.data.ignore = Ignore::Always;
92
93		TimestampValidatorBuilder {
94			_state: PhantomData,
95			data: self.data,
96		}
97	}
98
99	/// Specifies that the timestamp must be in the past (from the moment of validation) in order to be valid.
100	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
101	#[inline]
102	pub fn lt_now(mut self) -> TimestampValidatorBuilder<SetLtNow<S>>
103	where
104		S::LtNow: IsUnset,
105	{
106		self.data.lt_now = true;
107
108		TimestampValidatorBuilder {
109			_state: PhantomData,
110			data: self.data,
111		}
112	}
113
114	/// Specifies that the timestamp must be in the future (from the moment of validation) in order to be valid.
115	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
116	#[inline]
117	pub fn gt_now(mut self) -> TimestampValidatorBuilder<SetGtNow<S>>
118	where
119		S::GtNow: IsUnset,
120	{
121		self.data.gt_now = true;
122
123		TimestampValidatorBuilder {
124			_state: PhantomData,
125			data: self.data,
126		}
127	}
128
129	/// Specifies that the field must be set in order to be valid.
130	#[inline]
131	pub fn required(mut self) -> TimestampValidatorBuilder<SetRequired<S>>
132	where
133		S::Required: IsUnset,
134	{
135		self.data.required = true;
136
137		TimestampValidatorBuilder {
138			_state: PhantomData,
139			data: self.data,
140		}
141	}
142
143	/// Specifies that only this specific value will be considered valid for this field.
144	#[inline]
145	pub fn const_(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetConst<S>>
146	where
147		S::Const: IsUnset,
148	{
149		self.data.const_ = Some(val);
150
151		TimestampValidatorBuilder {
152			_state: PhantomData,
153			data: self.data,
154		}
155	}
156
157	/// Specifies that the timestamp must be earlier than the specified value in order to be valid.
158	#[inline]
159	pub fn lt(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetLt<S>>
160	where
161		S::Lt: IsUnset,
162	{
163		self.data.lt = Some(val);
164
165		TimestampValidatorBuilder {
166			_state: PhantomData,
167			data: self.data,
168		}
169	}
170
171	/// Specifies that the timestamp must be earlier than or equal to the specified value in order to be valid.
172	#[inline]
173	pub fn lte(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetLte<S>>
174	where
175		S::Lte: IsUnset,
176	{
177		self.data.lte = Some(val);
178
179		TimestampValidatorBuilder {
180			_state: PhantomData,
181			data: self.data,
182		}
183	}
184
185	/// Specifies that the timestamp must be later than the specified value in order to be valid.
186	#[inline]
187	pub fn gt(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetGt<S>>
188	where
189		S::Gt: IsUnset,
190	{
191		self.data.gt = Some(val);
192
193		TimestampValidatorBuilder {
194			_state: PhantomData,
195			data: self.data,
196		}
197	}
198
199	/// Specifies that the timestamp must be later than or equal to the specified value in order to be valid.
200	#[inline]
201	pub fn gte(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetGte<S>>
202	where
203		S::Gte: IsUnset,
204	{
205		self.data.gte = Some(val);
206
207		TimestampValidatorBuilder {
208			_state: PhantomData,
209			data: self.data,
210		}
211	}
212
213	/// Specifies that the timestamp must within the specified duration (in the past or in the future) from the moment of validation in order to be valid.
214	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
215	#[inline]
216	pub fn within(mut self, val: Duration) -> TimestampValidatorBuilder<SetWithin<S>>
217	where
218		S::Within: IsUnset,
219	{
220		self.data.within = Some(val);
221
222		TimestampValidatorBuilder {
223			_state: PhantomData,
224			data: self.data,
225		}
226	}
227
228	/// Specifies a tolerance to use when performing the `gt_now` check. This is for cases when you may want to check if a value is "from now onwards", but a tiny delay between the value's creation (which is the indended "now" moment) and its validation (which is when the "now" is evaluated) would cause the validation to fail.
229	///
230	/// # Example
231	/// ```
232	/// use protify::{*, proto_types::{Timestamp, Duration}};
233	///
234	/// // Our intended validation is that this value should not be in the past.
235	/// // So this should be valid.
236	/// let mut timestamp = Timestamp::now();
237	///
238	/// // But if we are strict, a single nanosecond may make it invalid
239	/// timestamp.nanos += 1;
240	///
241	/// let strict_validator = TimestampValidator::builder().gt_now().build();
242	/// assert!(strict_validator.validate(&timestamp).is_err());
243	///
244	/// // If we add a small tolerance, it becomes valid again
245	/// let validator_with_tolerance = TimestampValidator::builder().gt_now().now_tolerance(Duration::new(1, 0)).build();
246	/// assert!(validator_with_tolerance.validate(&timestamp).is_ok());
247	/// ```
248	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
249	#[inline]
250	pub fn now_tolerance(mut self, val: Duration) -> TimestampValidatorBuilder<SetNowTolerance<S>>
251	where
252		S::NowTolerance: IsUnset,
253	{
254		self.data.now_tolerance = val;
255
256		TimestampValidatorBuilder {
257			_state: PhantomData,
258			data: self.data,
259		}
260	}
261
262	/// Builds the validator.
263	#[inline]
264	pub fn build(self) -> TimestampValidator {
265		self.data
266	}
267}