#[ allow( clippy ::std_instead_of_alloc, clippy ::std_instead_of_core ) ]
mod private
{
use crate :: *;
use std ::slice;
use former ::Former;
#[ derive( Debug, Clone ) ]
pub struct Workspace
{
pub metadata: cargo_metadata ::Metadata,
pub crate_dir: CrateDir,
}
#[ derive( Debug, error ::typed ::Error ) ]
pub enum WorkspaceInitError
{
#[ error( "Path error. Details: {0}" ) ]
Path( #[ from ] PathError ),
#[ error( "Can not load workspace data. Details: {0}" ) ]
Metadata( #[ from ] cargo_metadata ::Error ),
#[ error( "I/O error: {0}" ) ]
IO( #[ from ] std ::io ::Error ),
}
impl TryFrom< CrateDir > for Workspace
{
type Error = WorkspaceInitError;
fn try_from( mut crate_dir: CrateDir ) -> Result< Self, Self ::Error >
{
let metadata = cargo_metadata ::MetadataCommand ::new()
.current_dir( crate_dir.as_ref() )
.no_deps()
.exec()?;
crate_dir = ( &metadata.workspace_root ).try_into()?;
Result ::Ok( Self
{
metadata,
crate_dir,
})
}
}
impl TryFrom< CurrentPath > for Workspace
{
type Error = WorkspaceInitError;
fn try_from( _cd: CurrentPath ) -> Result< Self, Self ::Error >
{
let abs_path = AbsolutePath ::try_from( std ::env ::current_dir()? )?;
let crate_dir = CrateDir ::try_from( abs_path )?;
Self ::try_from( crate_dir )
}
}
impl From< cargo_metadata ::Metadata > for Workspace
{
fn from( metadata: cargo_metadata ::Metadata ) -> Self
{
let path = metadata.workspace_root.as_std_path().parent().unwrap().to_path_buf();
let crate_dir = CrateDir ::try_from( path ).unwrap();
Self
{
metadata,
crate_dir,
}
}
}
impl Workspace
{
pub fn packages< 'a >( &'a self )
-> core ::iter ::Map
<
slice ::Iter< 'a, cargo_metadata ::Package >,
impl Fn( &'a cargo_metadata ::Package ) -> WorkspacePackageRef< 'a > + Clone,
>
{
self.metadata.packages.iter().map( WorkspacePackageRef ::from )
}
#[ must_use ]
pub fn workspace_root( &self ) -> CrateDir
{
CrateDir ::try_from( self.metadata.workspace_root.as_std_path() ).unwrap()
}
#[ must_use ]
pub fn target_directory( &self ) -> &std ::path ::Path
{
self.metadata.target_directory.as_std_path()
}
pub fn package_find_by_manifest< P >( &self, manifest_file: P ) -> Option< WorkspacePackageRef< '_ > >
where
P: AsRef< std ::path ::Path >,
{
self
.packages()
.find( | &p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref() )
}
#[ must_use ]
pub fn packages_which( &self ) -> PackagesFilterFormer< '_ >
{
PackagesFilter ::former().workspace( self )
}
}
#[ derive( Former ) ]
#[ allow( missing_debug_implementations ) ]
pub struct PackagesFilter< 'a >
{
workspace: &'a Workspace,
crate_dir: Box< dyn PackageFilter >,
manifest_file: Box< dyn PackageFilter >,
}
pub trait PackageFilter
{
fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool;
}
impl Default for Box< dyn PackageFilter >
{
fn default() -> Self
{
Box ::new( PackageFilterAll )
}
}
pub struct PackageFilterAll;
impl PackageFilter for PackageFilterAll
{
#[ inline( always ) ]
fn include( &self, _package: WorkspacePackageRef< '_ > ) -> bool
{
true
}
}
pub struct PackageFilterCrateDir( CrateDir );
impl PackageFilter for PackageFilterCrateDir
{
#[ inline( always ) ]
fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
{
self.0 == package.crate_dir().unwrap()
}
}
impl From< CrateDir > for Box< dyn PackageFilter >
{
#[ inline( always ) ]
fn from( src: CrateDir ) -> Self
{
Box ::new( PackageFilterCrateDir( src ) )
}
}
pub struct PackageFilterManifestFile( ManifestFile );
impl PackageFilter for PackageFilterManifestFile
{
#[ inline( always ) ]
fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
{
self.0 == package.manifest_file().unwrap()
}
}
impl From< ManifestFile > for Box< dyn PackageFilter >
{
#[ inline( always ) ]
fn from( src: ManifestFile ) -> Self
{
Box ::new( PackageFilterManifestFile( src ) )
}
}
impl< 'a > PackagesFilter< 'a >
{
pub fn new( workspace: &'a Workspace ) -> Self
{
Self
{
workspace,
crate_dir: Box ::default(),
manifest_file: Box ::default(),
}
}
#[ inline( always ) ]
#[ allow( clippy ::unused_self ) ]
pub fn iter( &'a self ) -> impl Iterator< Item = WorkspacePackageRef< 'a > > + Clone
{
std ::iter ::empty()
}
}
impl< 'a > PackagesFilterFormer< 'a >
{
#[ inline( always ) ]
pub fn find( self ) -> Option< WorkspacePackageRef< 'a > >
{
let formed = self.form();
formed
.workspace
.packages()
.find( | &p |
{
if !formed.crate_dir.include( p ) { return false }
if !formed.manifest_file.include( p ) { return false }
true
})
}
}
impl Entries for Workspace
{
fn entries( &self ) -> impl IterTrait< '_, SourceFile >
{
self
.packages()
.flat_map( | package | package.entries().collect :: < Vec< _ > >() )
.collect :: < Vec< _ > >()
.into_iter()
}
}
impl Sources for Workspace
{
fn sources( &self ) -> impl IterTrait< '_, SourceFile >
{
self
.packages()
.flat_map( | package | package.sources().collect :: < Vec< _ > >() )
.collect :: < Vec< _ > >().into_iter()
}
}
}
crate ::mod_interface!
{
exposed use WorkspaceInitError;
exposed use Workspace;
}