#[cfg(windows)]
#[macro_use]
extern crate lazy_static;
mod checker;
mod error;
mod finder;
#[cfg(windows)]
mod helper;
#[cfg(feature = "regex")]
use regex::Regex;
use std::env;
use std::fmt;
use std::path;
use std::ffi::OsStr;
use crate::checker::{CompositeChecker, ExecutableChecker, ExistedChecker};
pub use crate::error::*;
use crate::finder::Finder;
pub fn which<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
which_all(binary_name).and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
}
pub fn which_all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = path::PathBuf>> {
let cwd = env::current_dir().map_err(|_| Error::CannotGetCurrentDir)?;
which_in_all(binary_name, env::var_os("PATH"), cwd)
}
#[cfg(feature = "regex")]
pub fn which_re(regex: Regex) -> Result<impl Iterator<Item = path::PathBuf>> {
which_re_in(regex, env::var_os("PATH"))
}
pub fn which_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<path::PathBuf>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
which_in_all(binary_name, paths, cwd)
.and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
}
#[cfg(feature = "regex")]
pub fn which_re_in<T>(regex: Regex, paths: Option<T>) -> Result<impl Iterator<Item = path::PathBuf>>
where
T: AsRef<OsStr>,
{
let binary_checker = CompositeChecker::new()
.add_checker(Box::new(ExistedChecker::new()))
.add_checker(Box::new(ExecutableChecker::new()));
let finder = Finder::new();
finder.find_re(regex, paths, binary_checker)
}
pub fn which_in_all<T, U, V>(
binary_name: T,
paths: Option<U>,
cwd: V,
) -> Result<impl Iterator<Item = path::PathBuf>>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
let binary_checker = CompositeChecker::new()
.add_checker(Box::new(ExistedChecker::new()))
.add_checker(Box::new(ExecutableChecker::new()));
let finder = Finder::new();
finder.find(binary_name, paths, cwd, binary_checker)
}
#[derive(Clone, PartialEq)]
pub struct Path {
inner: path::PathBuf,
}
impl Path {
pub fn new<T: AsRef<OsStr>>(binary_name: T) -> Result<Path> {
which(binary_name).map(|inner| Path { inner })
}
pub fn all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = Path>> {
which_all(binary_name).map(|inner| inner.map(|inner| Path { inner }))
}
pub fn new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<Path>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
which_in(binary_name, paths, cwd).map(|inner| Path { inner })
}
pub fn all_in<T, U, V>(
binary_name: T,
paths: Option<U>,
cwd: V,
) -> Result<impl Iterator<Item = Path>>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
which_in_all(binary_name, paths, cwd).map(|inner| inner.map(|inner| Path { inner }))
}
pub fn as_path(&self) -> &path::Path {
self.inner.as_path()
}
pub fn into_path_buf(self) -> path::PathBuf {
self.inner
}
}
impl fmt::Debug for Path {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
impl std::ops::Deref for Path {
type Target = path::Path;
fn deref(&self) -> &path::Path {
self.inner.deref()
}
}
impl AsRef<path::Path> for Path {
fn as_ref(&self) -> &path::Path {
self.as_path()
}
}
impl AsRef<OsStr> for Path {
fn as_ref(&self) -> &OsStr {
self.as_os_str()
}
}
impl Eq for Path {}
impl PartialEq<path::PathBuf> for Path {
fn eq(&self, other: &path::PathBuf) -> bool {
self.inner == *other
}
}
impl PartialEq<Path> for path::PathBuf {
fn eq(&self, other: &Path) -> bool {
*self == other.inner
}
}
#[derive(Clone, PartialEq)]
pub struct CanonicalPath {
inner: path::PathBuf,
}
impl CanonicalPath {
pub fn new<T: AsRef<OsStr>>(binary_name: T) -> Result<CanonicalPath> {
which(binary_name)
.and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
.map(|inner| CanonicalPath { inner })
}
pub fn all<T: AsRef<OsStr>>(
binary_name: T,
) -> Result<impl Iterator<Item = Result<CanonicalPath>>> {
which_all(binary_name).map(|inner| {
inner.map(|inner| {
inner
.canonicalize()
.map_err(|_| Error::CannotCanonicalize)
.map(|inner| CanonicalPath { inner })
})
})
}
pub fn new_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<CanonicalPath>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
which_in(binary_name, paths, cwd)
.and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
.map(|inner| CanonicalPath { inner })
}
pub fn all_in<T, U, V>(
binary_name: T,
paths: Option<U>,
cwd: V,
) -> Result<impl Iterator<Item = Result<CanonicalPath>>>
where
T: AsRef<OsStr>,
U: AsRef<OsStr>,
V: AsRef<path::Path>,
{
which_in_all(binary_name, paths, cwd).map(|inner| {
inner.map(|inner| {
inner
.canonicalize()
.map_err(|_| Error::CannotCanonicalize)
.map(|inner| CanonicalPath { inner })
})
})
}
pub fn as_path(&self) -> &path::Path {
self.inner.as_path()
}
pub fn into_path_buf(self) -> path::PathBuf {
self.inner
}
}
impl fmt::Debug for CanonicalPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
impl std::ops::Deref for CanonicalPath {
type Target = path::Path;
fn deref(&self) -> &path::Path {
self.inner.deref()
}
}
impl AsRef<path::Path> for CanonicalPath {
fn as_ref(&self) -> &path::Path {
self.as_path()
}
}
impl AsRef<OsStr> for CanonicalPath {
fn as_ref(&self) -> &OsStr {
self.as_os_str()
}
}
impl Eq for CanonicalPath {}
impl PartialEq<path::PathBuf> for CanonicalPath {
fn eq(&self, other: &path::PathBuf) -> bool {
self.inner == *other
}
}
impl PartialEq<CanonicalPath> for path::PathBuf {
fn eq(&self, other: &CanonicalPath) -> bool {
*self == other.inner
}
}