You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
2.4 KiB
125 lines
2.4 KiB
use std::path::PathBuf;
|
|
use std::num::NonZeroUsize;
|
|
use std::{fmt,error};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum Recursion
|
|
{
|
|
None,
|
|
Limited(NonZeroUsize),
|
|
Unlimited,
|
|
}
|
|
|
|
impl Default for Recursion
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self::None
|
|
}
|
|
}
|
|
|
|
impl Recursion
|
|
{
|
|
/// Can we run at this depth?
|
|
pub fn can_run(&self, depth: usize) -> bool
|
|
{
|
|
debug_assert!(depth > 0, "Depth of 0 is invalid");
|
|
match self {
|
|
Self::None => depth == 1,
|
|
Self::Limited(limit) => depth <= limit.get(),
|
|
Self::Unlimited => true
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<usize> for Recursion
|
|
{
|
|
fn from(from: usize) -> Self
|
|
{
|
|
match from {
|
|
0 => Self::Unlimited,
|
|
1 => Self::None,
|
|
x => Self::Limited(unsafe {NonZeroUsize::new_unchecked(x)}),
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// Configuration for this run
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct Config
|
|
{
|
|
pub paths: Vec<PathBuf>,
|
|
pub recursive: Recursion,
|
|
pub max_tasks: Option<NonZeroUsize>,
|
|
}
|
|
|
|
/// The default `max_tasks`
|
|
#[inline(always)] pub fn max_tasks_cpus() -> Option<NonZeroUsize>
|
|
{
|
|
lazy_static! {
|
|
static ref CPUS: usize = num_cpus::get();
|
|
}
|
|
NonZeroUsize::new(*CPUS)
|
|
}
|
|
|
|
impl Default for Config
|
|
{
|
|
#[inline]
|
|
fn default() -> Self
|
|
{
|
|
Self {
|
|
paths: Vec::new(),
|
|
recursive: Default::default(),
|
|
max_tasks: max_tasks_cpus(),
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl Config
|
|
{
|
|
/// Validate this configuration instance.
|
|
pub fn validate(self) -> Result<Self, InvalidConfigError>
|
|
{
|
|
if self.paths.len() < 1 {
|
|
return Err(InvalidConfigError::NoPaths);
|
|
}
|
|
let paths: Result<Vec<_>, _> = self.paths.into_iter()
|
|
.map(|path| if !path.exists() { Err(InvalidConfigError::PathNotFound(path)) } else { Ok(path) })
|
|
.collect();
|
|
Ok(Self{
|
|
paths: paths?,
|
|
..self
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Error type for an invalid instance of `Config`.
|
|
#[derive(Debug)]
|
|
#[non_exhaustive]
|
|
pub enum InvalidConfigError
|
|
{
|
|
/// No paths were given.
|
|
NoPaths,
|
|
/// Non-existant path was given.
|
|
PathNotFound(PathBuf),
|
|
|
|
/// Unknown error
|
|
Other,
|
|
}
|
|
|
|
impl error::Error for InvalidConfigError{}
|
|
impl fmt::Display for InvalidConfigError
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
{
|
|
match self {
|
|
Self::NoPaths => write!(f, "No input paths were given. Cannot do anything"),
|
|
Self::PathNotFound(path) => write!(f, "Root path {:?} not found", path),
|
|
#[cold] _ => write!(f, "Unknown error"),
|
|
}
|
|
}
|
|
}
|