11//! Get config from the shader crate's `Cargo.toml` `[*.metadata.rust-gpu.*]`
22
3+ use std:: collections:: HashMap ;
4+
35use anyhow:: Context as _;
46use cargo_metadata:: MetadataCommand ;
57use serde_json:: Value ;
68
7- /// `Metadata` refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally
9+ /// A cache of metadata from various `Cargo.toml` files.
10+ ///
11+ /// "Metadata" refers to the `[metadata.*]` section of `Cargo.toml` that `cargo` formally
812/// ignores so that packages can implement their own behaviour with it.
9- #[ derive( Debug ) ]
10- pub struct Metadata ;
13+ #[ derive( Debug , Default ) ]
14+ pub struct MetadataCache {
15+ /// Cached result of `MetadataCommand::new().exec()`.
16+ inner : HashMap < std:: path:: PathBuf , cargo_metadata:: Metadata > ,
17+ }
18+
19+ impl MetadataCache {
20+ fn get_metadata (
21+ & mut self ,
22+ maybe_path_to_manifest_dir : Option < & std:: path:: Path > ,
23+ ) -> anyhow:: Result < & cargo_metadata:: Metadata > {
24+ let path = if let Some ( path) = maybe_path_to_manifest_dir {
25+ path. to_path_buf ( )
26+ } else {
27+ std:: env:: current_dir ( ) . context ( "cannot determine the current working directory" ) ?
28+ } ;
29+
30+ if !self . inner . contains_key ( & path) {
31+ let metadata = MetadataCommand :: new ( ) . current_dir ( & path) . exec ( ) ?;
32+ self . inner . insert ( path. clone ( ) , metadata) ;
33+ }
34+
35+ // UNWRAP: safe because we just inserted it
36+ Ok ( self . inner . get ( & path) . unwrap ( ) )
37+ }
1138
12- impl Metadata {
1339 /// Resolve a package name to a crate directory.
14- pub fn resolve_package_to_shader_crate ( package : & str ) -> anyhow:: Result < std:: path:: PathBuf > {
40+ pub fn resolve_package_to_shader_crate (
41+ & mut self ,
42+ package : & str ,
43+ ) -> anyhow:: Result < std:: path:: PathBuf > {
1544 log:: debug!( "resolving package '{package}' to shader crate" ) ;
16- let metadata = MetadataCommand :: new ( ) . exec ( ) ?;
45+ let metadata = self . get_metadata ( None ) ?;
46+
1747 let meta_package = metadata
1848 . packages
1949 . iter ( )
@@ -39,9 +69,9 @@ impl Metadata {
3969 /// First we generate the CLI arg defaults as JSON. Then on top of those we merge any config
4070 /// from the workspace `Cargo.toml`, then on top of those we merge any config from the shader
4171 /// crate's `Cargo.toml`.
42- pub fn as_json ( path : & std:: path:: PathBuf ) -> anyhow:: Result < Value > {
72+ pub fn as_json ( & mut self , path : & std:: path:: PathBuf ) -> anyhow:: Result < Value > {
4373 log:: debug!( "reading package metadata from {}" , path. display( ) ) ;
44- let cargo_json = Self :: get_cargo_toml_as_json ( path) ?;
74+ let cargo_json = self . get_cargo_toml_as_json ( path) ?;
4575 let config = Self :: merge_configs ( & cargo_json, path) ?;
4676 Ok ( config)
4777 }
@@ -90,9 +120,10 @@ impl Metadata {
90120
91121 /// Convert a `Cargo.toml` to JSON
92122 fn get_cargo_toml_as_json (
123+ & mut self ,
93124 path : & std:: path:: PathBuf ,
94125 ) -> anyhow:: Result < cargo_metadata:: Metadata > {
95- Ok ( MetadataCommand :: new ( ) . current_dir ( path ) . exec ( ) ? )
126+ self . get_metadata ( Some ( path . as_path ( ) ) ) . cloned ( )
96127 }
97128
98129 /// Get any `rust-gpu` metadata set in the crate's `Cargo.toml`
@@ -161,7 +192,7 @@ mod test {
161192 . exec ( )
162193 . unwrap ( ) ;
163194 metadata. packages . first_mut ( ) . unwrap ( ) . metadata = serde_json:: json!( { } ) ;
164- let configs = Metadata :: merge_configs ( & metadata, Path :: new ( "./" ) ) . unwrap ( ) ;
195+ let configs = MetadataCache :: merge_configs ( & metadata, Path :: new ( "./" ) ) . unwrap ( ) ;
165196 assert_eq ! ( configs[ "build" ] [ "release" ] , Value :: Bool ( true ) ) ;
166197 assert_eq ! (
167198 configs[ "install" ] [ "auto_install_rust_toolchain" ] ,
@@ -185,7 +216,7 @@ mod test {
185216 }
186217 }
187218 } ) ;
188- let configs = Metadata :: merge_configs ( & metadata, Path :: new ( "./" ) ) . unwrap ( ) ;
219+ let configs = MetadataCache :: merge_configs ( & metadata, Path :: new ( "./" ) ) . unwrap ( ) ;
189220 assert_eq ! ( configs[ "build" ] [ "release" ] , Value :: Bool ( false ) ) ;
190221 assert_eq ! (
191222 configs[ "install" ] [ "auto_install_rust_toolchain" ] ,
@@ -214,7 +245,7 @@ mod test {
214245 }
215246 }
216247 } ) ;
217- let configs = Metadata :: merge_configs ( & metadata, Path :: new ( "." ) ) . unwrap ( ) ;
248+ let configs = MetadataCache :: merge_configs ( & metadata, Path :: new ( "." ) ) . unwrap ( ) ;
218249 assert_eq ! ( configs[ "build" ] [ "release" ] , Value :: Bool ( false ) ) ;
219250 assert_eq ! (
220251 configs[ "install" ] [ "auto_install_rust_toolchain" ] ,
0 commit comments