use std::{
collections::{
hash_map::{IntoIter, Iter, IterMut, Keys},
HashMap,
},
error::Error,
fmt::Display,
hash::{Hash, Hasher},
ops::Index,
};
use crate::{
rule::{IntoRuleList, RuleList},
ser::Serializer,
value::ValueMap,
Value,
};
pub use field_name::{FieldName, FieldNames};
pub(crate) use field_name::{IntoFieldName, Parser};
pub use message::{IntoMessage, ValidPhrase};
use serde::{Deserialize, Serialize};
mod field_name;
mod lexer;
mod message;
pub mod string;
#[cfg(test)]
mod tests;
pub type Validator<'v, M> = InnerValidator<M, HashMap<MessageKey<'v>, M>>;
pub type ValidatorRefine<M> = InnerValidator<M, ()>;
#[doc(hidden)]
pub struct InnerValidator<M, List> {
rules: HashMap<FieldNames, RuleList<ValueMap, M>>,
message: List,
is_bail: bool,
}
impl<M> Validator<'_, M> {
pub fn new() -> Self {
Self::default()
}
pub fn validate<T>(self, data: T) -> Result<(), ValidatorError<M>>
where
T: Serialize,
{
let value = data.serialize(Serializer).unwrap();
debug_assert!(self.exist_field(&value));
let mut value_map = ValueMap::new(value);
self.inner_validate(&mut value_map).ok()
}
pub fn validate_mut<'de, T>(self, data: T) -> Result<T, ValidatorError<M>>
where
T: Serialize + serde::de::Deserialize<'de>,
{
let value = data.serialize(Serializer).unwrap();
debug_assert!(self.exist_field(&value));
let mut value_map = ValueMap::new(value);
self.inner_validate(&mut value_map)
.ok()
.map(|_| T::deserialize(value_map.value()).unwrap())
}
fn inner_validate(self, value_map: &mut ValueMap) -> ValidatorError<M> {
fn handle_msg<M>(
rules: RuleList<ValueMap, M>,
value_map: &mut ValueMap,
message: &mut HashMap<MessageKey<'_>, M>,
) -> Vec<M> {
rules
.call(value_map)
.into_iter()
.map(|(rule, msg)| {
message
.remove(&MessageKey::new(value_map.as_index().clone(), rule))
.unwrap_or(msg)
})
.collect()
}
self.iter_validate(value_map, handle_msg)
}
fn exit_message(&self, MessageKey { fields, rule }: &MessageKey) -> bool {
debug_assert!(
self.rule_get(fields).is_some(),
"the field \"{}\" not found in validator",
fields.as_str()
);
debug_assert!(
self.rule_get(fields).unwrap().contains(rule),
"rule \"{rule}\" is not found in rules"
);
true
}
}
impl<M> ValidatorRefine<M> {
pub fn new() -> Self {
Self::default()
}
pub fn validate<T, M2>(self, data: T) -> Result<(), ValidatorError<M2>>
where
T: Serialize,
M2: IntoMessage,
{
let value = data.serialize(Serializer).unwrap();
debug_assert!(self.exist_field(&value));
let mut value_map = ValueMap::new(value);
self.inner_validate(&mut value_map).ok()
}
pub fn validate_mut<'de, T, M2>(self, data: T) -> Result<T, ValidatorError<M2>>
where
T: Serialize + serde::de::Deserialize<'de>,
M2: IntoMessage,
{
let value = data.serialize(Serializer).unwrap();
debug_assert!(self.exist_field(&value));
let mut value_map = ValueMap::new(value);
self.inner_validate(&mut value_map)
.ok()
.map(|_| T::deserialize(value_map.value()).unwrap())
}
fn inner_validate<M2>(self, value_map: &mut ValueMap) -> ValidatorError<M2>
where
M2: IntoMessage,
{
self.iter_validate(value_map, |rules, data, _| rules.call_gen_message(data))
}
}
impl<'v, M> Validator<'v, M> {
pub fn message<const N: usize, Msg>(mut self, list: [(&'v str, Msg); N]) -> Self
where
Msg: Into<M>,
{
self.message.extend(list.map(|(key_str, v)| {
let msg_key = crate::panic_on_err!(field_name::parse_message(key_str));
debug_assert!(self.exit_message(&msg_key));
(msg_key, v.into())
}));
self
}
#[must_use]
pub fn map<M2>(self, f: fn(message: M) -> M2) -> Validator<'v, M2>
where
M: 'static,
M2: 'static,
{
Validator {
rules: self
.rules
.into_iter()
.map(|(field, list)| (field, list.map(f)))
.collect(),
message: self
.message
.into_iter()
.map(|(key, msg)| (key, f(msg)))
.collect(),
is_bail: self.is_bail,
}
}
}
impl<M, List> Default for InnerValidator<M, List>
where
List: Default,
{
fn default() -> Self {
Self {
rules: HashMap::new(),
message: List::default(),
is_bail: false,
}
}
}
impl<M, List> Clone for InnerValidator<M, List>
where
List: Clone,
{
fn clone(&self) -> Self {
Self {
rules: self.rules.clone(),
message: self.message.clone(),
is_bail: self.is_bail,
}
}
}
impl<M, List> InnerValidator<M, List> {
pub fn rule<F, R>(mut self, field: F, rule: R) -> Self
where
F: IntoFieldName,
R: IntoRuleList<ValueMap, M>,
{
let names = crate::panic_on_err!(field.into_field());
let mut rules = rule.into_list();
debug_assert!(rules.valid_name(), "invalid rule name");
self.rules
.entry(names)
.and_modify(|list| list.merge(&mut rules))
.or_insert(rules);
self
}
pub fn bail(mut self) -> Self {
self.is_bail = true;
self
}
fn exist_field(&self, value: &Value) -> bool {
for (field, _) in self.rules.iter() {
if value.get_with_names(field).is_none() {
panic!("field `{}` is not found", field.as_str());
}
}
true
}
#[inline(always)]
fn rule_get(&self, names: &FieldNames) -> Option<&RuleList<ValueMap, M>> {
self.rules.get(names)
}
fn iter_validate<F, T>(self, value_map: &mut ValueMap, handle_msg: F) -> ValidatorError<T>
where
F: Fn(RuleList<ValueMap, M>, &mut ValueMap, &mut List) -> Vec<T>,
{
let mut resp_message = ValidatorError::with_capacity(self.rules.len());
let Self {
rules,
mut message,
is_bail,
} = self;
for (mut names, mut rules) in rules.into_iter() {
if is_bail {
rules.set_bail();
}
value_map.index(names);
let field_msg = handle_msg(rules, value_map, &mut message);
names = value_map.take_index();
resp_message.push(names, field_msg);
if is_bail && !resp_message.is_empty() {
resp_message.shrink_to(1);
return resp_message;
}
}
resp_message.shrink_to_fit();
resp_message
}
#[cfg(test)]
pub(crate) fn get_message(&self) -> &List {
&self.message
}
}
impl<M> From<Validator<'_, M>> for ValidatorRefine<M> {
fn from(value: Validator<'_, M>) -> Self {
let Validator { rules, is_bail, .. } = value;
Self {
rules,
message: (),
is_bail,
}
}
}
pub trait Validatable<V, E> {
fn validate(&self, validator: V) -> Result<(), E>;
fn validate_mut<'de>(self, validator: V) -> Result<Self, E>
where
Self: Deserialize<'de>;
}
impl<T, M> Validatable<Validator<'_, M>, ValidatorError<M>> for T
where
T: Serialize,
M: 'static,
{
fn validate(&self, validator: Validator<M>) -> Result<(), ValidatorError<M>> {
validator.validate(self)
}
fn validate_mut<'de>(self, validator: Validator<M>) -> Result<Self, ValidatorError<M>>
where
Self: Deserialize<'de>,
{
validator.validate_mut(self)
}
}
impl<T, M, M2> Validatable<ValidatorRefine<M>, ValidatorError<M2>> for T
where
T: Serialize,
M: 'static,
M2: IntoMessage,
{
fn validate(&self, validator: ValidatorRefine<M>) -> Result<(), ValidatorError<M2>> {
validator.validate(self)
}
fn validate_mut<'de>(self, validator: ValidatorRefine<M>) -> Result<Self, ValidatorError<M2>>
where
Self: Deserialize<'de>,
{
validator.validate_mut(self)
}
}
pub type ValidatorError<M> = InnerValidatorError<FieldNames, M>;
pub struct InnerValidatorError<F, M> {
message: HashMap<F, Vec<M>>,
}
impl<F: Clone, M: Clone> Clone for InnerValidatorError<F, M> {
fn clone(&self) -> Self {
Self {
message: self.message.clone(),
}
}
}
impl<F: Hash + Eq, M: PartialEq> PartialEq for InnerValidatorError<F, M> {
fn eq(&self, other: &Self) -> bool {
self.message == other.message
}
}
impl<M, F> std::fmt::Debug for InnerValidatorError<F, M>
where
M: std::fmt::Debug,
F: std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ValidatorError")
.field("message", &self.message)
.finish()
}
}
impl<M> Index<&str> for ValidatorError<M> {
type Output = Vec<M>;
fn index(&self, index: &str) -> &Self::Output {
self.message
.get(&(index.into()))
.expect("this field is not found")
}
}
impl<M> Index<&str> for InnerValidatorError<String, M> {
type Output = Vec<M>;
fn index(&self, index: &str) -> &Self::Output {
self.message.get(index).expect("this field is not found")
}
}
impl<F, M> Serialize for InnerValidatorError<F, M>
where
F: serde::Serialize,
M: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.message.serialize(serializer)
}
}
impl<F, M> Display for InnerValidatorError<F, M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
"validate error".fmt(f)
}
}
impl<F, M> Error for InnerValidatorError<F, M>
where
M: std::fmt::Debug,
F: std::fmt::Debug,
{
}
impl<F, M> InnerValidatorError<F, M>
where
F: Eq + Hash,
{
pub fn new() -> Self {
Self {
message: HashMap::new(),
}
}
fn with_capacity(capacity: usize) -> Self {
Self {
message: HashMap::with_capacity(capacity),
}
}
fn shrink_to_fit(&mut self) {
self.message.shrink_to_fit()
}
fn shrink_to(&mut self, min_capacity: usize) {
self.message.shrink_to(min_capacity)
}
pub fn map<M2>(self, f: fn(M) -> M2) -> InnerValidatorError<F, M2> {
InnerValidatorError {
message: self
.message
.into_iter()
.map(|(name, msg)| (name, msg.into_iter().map(f).collect()))
.collect(),
}
}
pub fn is_empty(&self) -> bool {
self.message.is_empty()
}
pub fn is_ok(&self) -> bool {
self.is_empty()
}
pub fn len(&self) -> usize {
self.message.len()
}
pub fn total(&self) -> usize {
self.message.values().map(|msg| msg.len()).sum()
}
fn ok(self) -> Result<(), Self> {
if self.message.is_empty() {
Ok(())
} else {
Err(self)
}
}
}
impl<M> ValidatorError<M> {
fn push(&mut self, field_name: FieldNames, message: Vec<M>) {
if !message.is_empty() {
self.message.insert(field_name, message);
}
}
pub fn get<K: IntoFieldName>(&self, key: K) -> Option<&Vec<M>> {
let k = key.into_field().ok()?;
self.message.get(&k)
}
pub fn get_key_value<K: IntoFieldName>(&self, key: K) -> Option<(&FieldNames, &Vec<M>)> {
let k = key.into_field().ok()?;
self.message.get_key_value(&k)
}
pub fn contains_key<K: IntoFieldName>(&self, key: K) -> bool {
match key.into_field() {
Ok(k) => self.message.contains_key(&k),
Err(_) => false,
}
}
pub fn keys(&self) -> Keys<'_, FieldNames, Vec<M>> {
self.message.keys()
}
pub fn iter(&self) -> Iter<'_, FieldNames, Vec<M>> {
self.message.iter()
}
pub fn iter_mut(&mut self) -> IterMut<'_, FieldNames, Vec<M>> {
self.message.iter_mut()
}
}
impl<'a, F, M> IntoIterator for &'a mut InnerValidatorError<F, M> {
type Item = (&'a F, &'a mut Vec<M>);
type IntoIter = IterMut<'a, F, Vec<M>>;
fn into_iter(self) -> Self::IntoIter {
self.message.iter_mut()
}
}
impl<F, M> IntoIterator for InnerValidatorError<F, M> {
type Item = (F, Vec<M>);
type IntoIter = IntoIter<F, Vec<M>>;
fn into_iter(self) -> Self::IntoIter {
self.message.into_iter()
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct MessageKey<'key> {
fields: FieldNames,
rule: &'key str,
}
impl Hash for MessageKey<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.fields.hash(state);
self.rule.hash(state);
}
}
impl<'key> MessageKey<'key> {
pub(crate) fn new(fields: FieldNames, rule: &'key str) -> Self {
Self { fields, rule }
}
}
#[test]
#[cfg(feature = "full")]
fn test_refine() {
use crate::available::Required;
let _ = ValidatorRefine::new().rule("foo", Required);
}