protify 0.1.4

A Rust-first protobuf framework to generate packages from rust code, with validation included
Documentation
#[doc(hidden)]
pub mod state;
use crate::validators::*;
pub(crate) use state::*;

use proto_types::{Duration, Timestamp};

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TimestampValidatorBuilder<S: State = Empty> {
	_state: PhantomData<S>,

	data: TimestampValidator,
}

impl ProtoValidation for Timestamp {
	#[doc(hidden)]
	type Target = Self;
	#[doc(hidden)]
	type Stored = Self;
	type Validator = TimestampValidator;
	type ValidatorBuilder = TimestampValidatorBuilder;

	#[doc(hidden)]
	type UniqueStore<'a>
		= CopyHybridStore<Self>
	where
		Self: 'a;

	#[doc(hidden)]
	const HAS_DEFAULT_VALIDATOR: bool = false;
}
impl<S: State> ValidatorBuilderFor<Timestamp> for TimestampValidatorBuilder<S> {
	type Validator = TimestampValidator;
	#[inline]
	fn build_validator(self) -> TimestampValidator {
		self.build()
	}
}

impl<S: State> Default for TimestampValidatorBuilder<S> {
	#[inline]
	fn default() -> Self {
		Self {
			_state: PhantomData,
			data: TimestampValidator::default(),
		}
	}
}

impl TimestampValidator {
	#[must_use]
	#[inline]
	pub fn builder() -> TimestampValidatorBuilder {
		TimestampValidatorBuilder::default()
	}
}

impl<S: State> From<TimestampValidatorBuilder<S>> for ProtoOption {
	#[inline(never)]
	#[cold]
	fn from(value: TimestampValidatorBuilder<S>) -> Self {
		value.build().into()
	}
}

#[allow(
	clippy::must_use_candidate,
	clippy::use_self,
	clippy::return_self_not_must_use
)]
impl<S: State> TimestampValidatorBuilder<S> {
	custom_error_messages_method!(Timestamp);

	/// Adds a [`CelProgram`] to this validator.
	#[inline]
	pub fn cel(mut self, program: CelProgram) -> TimestampValidatorBuilder<S> {
		self.data.cel.push(program);

		TimestampValidatorBuilder {
			_state: PhantomData,
			..self
		}
	}

	/// Specifies that this validator should always be ignored.
	#[inline]
	pub fn ignore_always(mut self) -> TimestampValidatorBuilder<SetIgnore<S>>
	where
		S::Ignore: IsUnset,
	{
		self.data.ignore = Ignore::Always;

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be in the past (from the moment of validation) in order to be valid.
	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
	#[inline]
	pub fn lt_now(mut self) -> TimestampValidatorBuilder<SetLtNow<S>>
	where
		S::LtNow: IsUnset,
	{
		self.data.lt_now = true;

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be in the future (from the moment of validation) in order to be valid.
	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
	#[inline]
	pub fn gt_now(mut self) -> TimestampValidatorBuilder<SetGtNow<S>>
	where
		S::GtNow: IsUnset,
	{
		self.data.gt_now = true;

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the field must be set in order to be valid.
	#[inline]
	pub fn required(mut self) -> TimestampValidatorBuilder<SetRequired<S>>
	where
		S::Required: IsUnset,
	{
		self.data.required = true;

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that only this specific value will be considered valid for this field.
	#[inline]
	pub fn const_(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetConst<S>>
	where
		S::Const: IsUnset,
	{
		self.data.const_ = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be earlier than the specified value in order to be valid.
	#[inline]
	pub fn lt(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetLt<S>>
	where
		S::Lt: IsUnset,
	{
		self.data.lt = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be earlier than or equal to the specified value in order to be valid.
	#[inline]
	pub fn lte(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetLte<S>>
	where
		S::Lte: IsUnset,
	{
		self.data.lte = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be later than the specified value in order to be valid.
	#[inline]
	pub fn gt(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetGt<S>>
	where
		S::Gt: IsUnset,
	{
		self.data.gt = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Specifies that the timestamp must be later than or equal to the specified value in order to be valid.
	#[inline]
	pub fn gte(mut self, val: Timestamp) -> TimestampValidatorBuilder<SetGte<S>>
	where
		S::Gte: IsUnset,
	{
		self.data.gte = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// 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.
	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
	#[inline]
	pub fn within(mut self, val: Duration) -> TimestampValidatorBuilder<SetWithin<S>>
	where
		S::Within: IsUnset,
	{
		self.data.within = Some(val);

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// 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.
	///
	/// # Example
	/// ```
	/// use protify::{*, proto_types::{Timestamp, Duration}};
	///
	/// // Our intended validation is that this value should not be in the past.
	/// // So this should be valid.
	/// let mut timestamp = Timestamp::now();
	///
	/// // But if we are strict, a single nanosecond may make it invalid
	/// timestamp.nanos += 1;
	///
	/// let strict_validator = TimestampValidator::builder().gt_now().build();
	/// assert!(strict_validator.validate(&timestamp).is_err());
	///
	/// // If we add a small tolerance, it becomes valid again
	/// let validator_with_tolerance = TimestampValidator::builder().gt_now().now_tolerance(Duration::new(1, 0)).build();
	/// assert!(validator_with_tolerance.validate(&timestamp).is_ok());
	/// ```
	#[cfg(all(feature = "chrono", any(feature = "std", feature = "chrono-wasm")))]
	#[inline]
	pub fn now_tolerance(mut self, val: Duration) -> TimestampValidatorBuilder<SetNowTolerance<S>>
	where
		S::NowTolerance: IsUnset,
	{
		self.data.now_tolerance = val;

		TimestampValidatorBuilder {
			_state: PhantomData,
			data: self.data,
		}
	}

	/// Builds the validator.
	#[inline]
	pub fn build(self) -> TimestampValidator {
		self.data
	}
}