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(())
    }
}