1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use std::path::Path; use crate::error::Error; use crate::error::severity::Severity; use crate::log::Logger; use crate::id::Id; use serde::export::PhantomData; pub trait Validator<T> { fn validate(&self, _: &mut Logger, _: &T) -> Result<(), Error>; } #[derive(Copy, Clone)] pub enum PathValidatorKind { DirectoryPath, ExistingFile, FilePath, } #[derive(Copy, Clone)] pub struct PathValidator(pub Severity, pub PathValidatorKind); impl Validator<&Path> for PathValidator { fn validate(&self, logger: &mut Logger, item: &&Path) -> Result<(), Error> { let severity = self.0; let data = self.1; match data { PathValidatorKind::DirectoryPath => if !item.is_dir() || !item.exists() { let desc = format!("Not a valid directory: '{:?}'.", item); logger.log(severity, &desc); if severity >= Severity::Error { Err(Error::InvalidDirectory(item.to_path_buf()))?; } }, PathValidatorKind::ExistingFile => if !item.is_file() || !item.exists() { let desc = format!("File does not exists: '{:?}'.", item); logger.log(severity, &desc); if severity >= Severity::Error { Err(Error::FileNotFound(item.to_path_buf()))?; } } PathValidatorKind::FilePath => if item.is_dir() { let desc = format!("Not a valid file path: '{:?}'.", item); logger.log(severity, &desc); if severity >= Severity::Error { Err(Error::InvalidFilePath(item.to_path_buf()))?; } } } Ok(()) } } impl<T> Validator<T> for Fn(&mut Logger, &T) -> Result<(), Error> { fn validate(&self, logger: &mut Logger, item: &T) -> Result<(), Error> { self(logger, item) } } pub struct IdValidator<I: Id, V: Validator<I>> (pub Severity, pub V, pub PhantomData<I>); impl<I, V> Validator<Vec<I>> for IdValidator<I, V> where I: Id, V: Validator<I> { fn validate(&self, logger: &mut Logger, item: &Vec<I>) -> Result<(), Error> { let mut uniques = Vec::new(); for val in item { if uniques.contains(&val.id()) || uniques.contains(&val.id()) { let desc = format!("Unique item declared twice."); logger.log(self.0, &desc); Err(Error::DuplicateItem("temp".to_owned()))?; } else { self.1.validate(logger, val)?; uniques.push(val.id()); } } Ok(()) } } impl<I, V> Validator<Vec<&I>> for IdValidator<I, V> where I: Id, V: Validator<I> { fn validate(&self, logger: &mut Logger, item: &Vec<&I>) -> Result<(), Error> { let mut uniques = Vec::new(); for &val in item { if uniques.contains(&val.id()) || uniques.contains(&val.id()) { let desc = format!("Unique item declared twice."); logger.log(self.0, &desc); Err(Error::DuplicateItem("temp".to_owned()))?; } else { self.1.validate(logger, val)?; uniques.push(val.id()); } } Ok(()) } }