use std::error::Error;
use super::super::BoundValidationContext;
use super::super::DependencySpec;
use super::super::ExecutionError;
use super::super::ExecutionErrorKind;
use super::super::InputType;
use super::super::PreparedOutcome;
use super::super::PreparedValidator;
use super::super::ValidationValue;
use crate::Validator;
use crate::ViolationDraft;
pub(in crate::binding) struct ContextualTextValidatorAdapter<V, M> {
validator: V,
map_error: M,
dependencies: &'static [DependencySpec],
}
impl<V, M> ContextualTextValidatorAdapter<V, M> {
#[must_use]
#[inline]
pub(in crate::binding) const fn new(validator: V, map_error: M, dependencies: &'static [DependencySpec]) -> Self {
Self {
validator,
map_error,
dependencies,
}
}
}
impl<V, E, M> PreparedValidator for ContextualTextValidatorAdapter<V, M>
where
V: for<'a> Validator<str, BoundValidationContext<'a>, Error = E> + Send + Sync + 'static,
E: Error + 'static,
M: Fn(E) -> ViolationDraft + Send + Sync + 'static,
{
#[inline]
fn input_type(&self) -> InputType {
InputType::Text
}
#[inline]
fn dependency_specs(&self) -> &'static [DependencySpec] {
self.dependencies
}
fn validate(
&self,
value: ValidationValue<'_>,
context: &BoundValidationContext<'_>,
) -> Result<PreparedOutcome, ExecutionError> {
let text = value
.as_text()
.ok_or_else(|| ExecutionError::new(ExecutionErrorKind::InputTypeMismatch))?;
match self.validator.validate(text, context) {
Ok(()) => Ok(PreparedOutcome::valid()),
Err(error) => Ok(PreparedOutcome::invalid(vec![(self.map_error)(error)])
.expect("a domain error maps to one violation draft")),
}
}
}