willbe/entity/
workspace.rs1#[ allow( clippy ::std_instead_of_alloc, clippy ::std_instead_of_core ) ]
2mod private
3{
4
5 use crate :: *;
6 use std ::slice;
9 use former ::Former;
10
11 #[ derive( Debug, Clone ) ]
13 pub struct Workspace
14 {
15 pub metadata: cargo_metadata ::Metadata,
17 pub crate_dir: CrateDir,
19 }
20
21 #[ derive( Debug, error ::typed ::Error ) ]
23 pub enum WorkspaceInitError
24 {
25 #[ error( "Path error. Details: {0}" ) ]
27 Path( #[ from ] PathError ),
28 #[ error( "Can not load workspace data. Details: {0}" ) ]
30 Metadata( #[ from ] cargo_metadata ::Error ),
31 #[ error( "I/O error: {0}" ) ]
33 IO( #[ from ] std ::io ::Error ),
34 }
35
36 impl TryFrom< CrateDir > for Workspace
37 {
38 type Error = WorkspaceInitError;
39
40 fn try_from( mut crate_dir: CrateDir ) -> Result< Self, Self ::Error >
42 {
43 let metadata = cargo_metadata ::MetadataCommand ::new()
44 .current_dir( crate_dir.as_ref() )
45 .no_deps()
46 .exec()?;
47 crate_dir = ( &metadata.workspace_root ).try_into()?;
49 Result ::Ok( Self
50 {
51 metadata,
52 crate_dir,
53 })
54 }
55
56 }
57
58 impl TryFrom< CurrentPath > for Workspace
59 {
60 type Error = WorkspaceInitError;
61
62 fn try_from( _cd: CurrentPath ) -> Result< Self, Self ::Error >
64 {
65 let abs_path = AbsolutePath ::try_from( std ::env ::current_dir()? )?;
66 let crate_dir = CrateDir ::try_from( abs_path )?;
67 Self ::try_from( crate_dir )
68 }
69
70 }
71
72 impl From< cargo_metadata ::Metadata > for Workspace
73 {
74 fn from( metadata: cargo_metadata ::Metadata ) -> Self
75 {
76 let path = metadata.workspace_root.as_std_path().parent().unwrap().to_path_buf();
78 let crate_dir = CrateDir ::try_from( path ).unwrap();
79 Self
80 {
81 metadata,
82 crate_dir,
83 }
84 }
85 }
86
87 impl Workspace
88 {
89
90 pub fn packages< 'a >( &'a self )
92 -> core ::iter ::Map
93 <
94 slice ::Iter< 'a, cargo_metadata ::Package >,
95 impl Fn( &'a cargo_metadata ::Package ) -> WorkspacePackageRef< 'a > + Clone,
96 >
97 {
98 self.metadata.packages.iter().map( WorkspacePackageRef ::from )
99 }
100
101 #[ must_use ]
106 pub fn workspace_root( &self ) -> CrateDir
107 {
108 CrateDir ::try_from( self.metadata.workspace_root.as_std_path() ).unwrap()
110 }
111
112 #[ must_use ]
114 pub fn target_directory( &self ) -> &std ::path ::Path
115 {
116 self.metadata.target_directory.as_std_path()
117 }
118
119 pub fn package_find_by_manifest< P >( &self, manifest_file: P ) -> Option< WorkspacePackageRef< '_ > >
124 where
125 P: AsRef< std ::path ::Path >,
126 {
127 self
128 .packages()
129 .find( | &p | p.manifest_file().unwrap().as_ref() == manifest_file.as_ref() )
130 }
131
132 #[ must_use ]
134 pub fn packages_which( &self ) -> PackagesFilterFormer< '_ >
135 {
136 PackagesFilter ::former().workspace( self )
138 }
139
140 }
141
142
143 #[ derive( Former ) ]
144 #[ allow( missing_debug_implementations ) ]
146 pub struct PackagesFilter< 'a >
147 {
148 workspace: &'a Workspace,
149 crate_dir: Box< dyn PackageFilter >,
150 manifest_file: Box< dyn PackageFilter >,
151 }
152
153 pub trait PackageFilter
154 {
155 fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool;
156 }
157
158 impl Default for Box< dyn PackageFilter >
159 {
160 fn default() -> Self
161 {
162 Box ::new( PackageFilterAll )
163 }
164 }
165
166 pub struct PackageFilterAll;
167 impl PackageFilter for PackageFilterAll
168 {
169 #[ inline( always ) ]
170 fn include( &self, _package: WorkspacePackageRef< '_ > ) -> bool
171 {
172 true
173 }
174 }
175
176 pub struct PackageFilterCrateDir( CrateDir );
177 impl PackageFilter for PackageFilterCrateDir
178 {
179 #[ inline( always ) ]
180 fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
181 {
182 self.0 == package.crate_dir().unwrap()
183 }
184 }
185
186 impl From< CrateDir > for Box< dyn PackageFilter >
187 {
188 #[ inline( always ) ]
189 fn from( src: CrateDir ) -> Self
190 {
191 Box ::new( PackageFilterCrateDir( src ) )
192 }
193 }
194
195 pub struct PackageFilterManifestFile( ManifestFile );
196 impl PackageFilter for PackageFilterManifestFile
197 {
198 #[ inline( always ) ]
199 fn include( &self, package: WorkspacePackageRef< '_ > ) -> bool
200 {
201 self.0 == package.manifest_file().unwrap()
202 }
203 }
204
205 impl From< ManifestFile > for Box< dyn PackageFilter >
206 {
207 #[ inline( always ) ]
208 fn from( src: ManifestFile ) -> Self
209 {
210 Box ::new( PackageFilterManifestFile( src ) )
211 }
212 }
213
214 impl< 'a > PackagesFilter< 'a >
215 {
216
217 pub fn new( workspace: &'a Workspace ) -> Self
218 {
219 Self
220 {
221 workspace,
222 crate_dir: Box ::default(),
223 manifest_file: Box ::default(),
224 }
225 }
226
227 #[ inline( always ) ]
228 #[ allow( clippy ::unused_self ) ]
229 pub fn iter( &'a self ) -> impl Iterator< Item = WorkspacePackageRef< 'a > > + Clone
230 {
231
232 std ::iter ::empty()
243 }
244
245 }
246
247 impl< 'a > PackagesFilterFormer< 'a >
248 {
249 #[ inline( always ) ]
250 pub fn find( self ) -> Option< WorkspacePackageRef< 'a > >
252 {
253 let formed = self.form();
254
255 formed
256 .workspace
257 .packages()
258 .find( | &p |
259 {
260 if !formed.crate_dir.include( p ) { return false }
261 if !formed.manifest_file.include( p ) { return false }
262 true
263 })
264 }
273 }
274
275 impl Entries for Workspace
276 {
277 fn entries( &self ) -> impl IterTrait< '_, SourceFile >
278 {
279 self
280 .packages()
281 .flat_map( | package | package.entries().collect :: < Vec< _ > >() )
282 .collect :: < Vec< _ > >()
283 .into_iter()
284 }
285 }
286
287 impl Sources for Workspace
288 {
289 fn sources( &self ) -> impl IterTrait< '_, SourceFile >
290 {
291 self
292 .packages()
293 .flat_map( | package | package.sources().collect :: < Vec< _ > >() )
294 .collect :: < Vec< _ > >().into_iter()
295 }
297 }
298
299}
300
301crate ::mod_interface!
304{
305 exposed use WorkspaceInitError;
306 exposed use Workspace;
307}