use std::sync::Arc;
use prost_reflect::{
DynamicMessage, FieldDescriptor, MessageDescriptor, OneofDescriptor, ReflectMessage,
};
use prost_types::Timestamp;
#[non_exhaustive]
pub enum ValidatorOption {
FailFast,
DisableLazy,
NowFn(Arc<dyn Fn() -> Timestamp + Send + Sync>),
AdditionalDescriptorSetBytes(Vec<u8>),
MessageDescriptors(Vec<MessageDescriptor>),
AllowUnknownFields,
}
#[non_exhaustive]
pub enum ValidationOption {
FailFast,
Filter(Arc<dyn Filter>),
NowFn(Arc<dyn Fn() -> Timestamp + Send + Sync>),
}
pub trait Filter: Send + Sync {
fn should_validate(&self, message: &DynamicMessage, descriptor: &MessageDescriptor) -> bool;
fn should_validate_field(&self, message: &DynamicMessage, _field: &FieldDescriptor) -> bool {
let descriptor = message.descriptor();
self.should_validate(message, &descriptor)
}
fn should_validate_oneof(&self, message: &DynamicMessage, _oneof: &OneofDescriptor) -> bool {
let descriptor = message.descriptor();
self.should_validate(message, &descriptor)
}
}
pub(crate) struct NopFilter;
impl Filter for NopFilter {
fn should_validate(&self, _message: &DynamicMessage, _descriptor: &MessageDescriptor) -> bool {
true
}
}
pub(crate) struct ValidationConfig {
pub fail_fast: bool,
pub filter: Arc<dyn Filter>,
pub now_fn: Arc<dyn Fn() -> Timestamp + Send + Sync>,
}
pub(crate) fn default_now_fn() -> Arc<dyn Fn() -> Timestamp + Send + Sync> {
Arc::new(|| {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default();
#[allow(clippy::cast_possible_wrap)]
Timestamp {
seconds: now.as_secs() as i64,
nanos: now.subsec_nanos() as i32,
}
})
}
impl Default for ValidationConfig {
fn default() -> Self {
Self {
fail_fast: false,
filter: Arc::new(NopFilter),
now_fn: default_now_fn(),
}
}
}