@@ -6,7 +6,10 @@ use figment::{
66} ;
77use foundry_compilers:: ProjectPathsConfig ;
88use heck:: ToSnakeCase ;
9- use std:: path:: { Path , PathBuf } ;
9+ use std:: {
10+ cell:: OnceCell ,
11+ path:: { Path , PathBuf } ,
12+ } ;
1013
1114pub ( crate ) trait ProviderExt : Provider + Sized {
1215 fn rename (
@@ -46,18 +49,19 @@ impl<P: Provider> ProviderExt for P {}
4649/// A convenience provider to retrieve a toml file.
4750/// This will return an error if the env var is set but the file does not exist
4851pub ( crate ) struct TomlFileProvider {
49- pub env_var : Option < & ' static str > ,
50- pub default : PathBuf ,
51- pub cache : Option < Result < Map < Profile , Dict > , Error > > ,
52+ env_var : Option < & ' static str > ,
53+ env_val : OnceCell < Option < String > > ,
54+ default : PathBuf ,
55+ cache : OnceCell < Result < Map < Profile , Dict > , Error > > ,
5256}
5357
5458impl TomlFileProvider {
55- pub ( crate ) fn new ( env_var : Option < & ' static str > , default : impl Into < PathBuf > ) -> Self {
56- Self { env_var, default : default . into ( ) , cache : None }
59+ pub ( crate ) fn new ( env_var : Option < & ' static str > , default : PathBuf ) -> Self {
60+ Self { env_var, env_val : OnceCell :: new ( ) , default , cache : OnceCell :: new ( ) }
5761 }
5862
59- fn env_val ( & self ) -> Option < String > {
60- self . env_var . and_then ( Env :: var)
63+ fn env_val ( & self ) -> Option < & str > {
64+ self . env_val . get_or_init ( || self . env_var . and_then ( Env :: var) ) . as_deref ( )
6165 }
6266
6367 fn file ( & self ) -> PathBuf {
@@ -74,11 +78,6 @@ impl TomlFileProvider {
7478 false
7579 }
7680
77- pub ( crate ) fn cached ( mut self ) -> Self {
78- self . cache = Some ( self . read ( ) ) ;
79- self
80- }
81-
8281 /// Reads and processes the TOML configuration file, handling inheritance if configured.
8382 fn read ( & self ) -> Result < Map < Profile , Dict > , Error > {
8483 use serde:: de:: Error as _;
@@ -248,7 +247,7 @@ impl Provider for TomlFileProvider {
248247 }
249248
250249 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
251- if let Some ( cache ) = self . cache . as_ref ( ) { cache . clone ( ) } else { self . read ( ) }
250+ self . cache . get_or_init ( || self . read ( ) ) . clone ( )
252251 }
253252}
254253
@@ -262,17 +261,21 @@ impl<P: Provider> Provider for ForcedSnakeCaseData<P> {
262261 }
263262
264263 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
265- let mut map = Map :: new ( ) ;
266- for ( profile, dict) in self . 0 . data ( ) ? {
264+ let mut map = self . 0 . data ( ) ? ;
265+ for ( profile, dict) in & mut map {
267266 if Config :: STANDALONE_SECTIONS . contains ( & profile. as_ref ( ) ) {
268267 // don't force snake case for keys in standalone sections
269- map. insert ( profile, dict) ;
270268 continue ;
271269 }
272- map. insert ( profile, dict. into_iter ( ) . map ( |( k, v) | ( k. to_snake_case ( ) , v) ) . collect ( ) ) ;
270+ let dict2 = std:: mem:: take ( dict) ;
271+ * dict = dict2. into_iter ( ) . map ( |( k, v) | ( k. to_snake_case ( ) , v) ) . collect ( ) ;
273272 }
274273 Ok ( map)
275274 }
275+
276+ fn profile ( & self ) -> Option < Profile > {
277+ self . 0 . profile ( )
278+ }
276279}
277280
278281/// A Provider that handles breaking changes in toml files
@@ -299,14 +302,14 @@ impl<P: Provider> Provider for BackwardsCompatTomlProvider<P> {
299302 dict. insert ( "solc" . to_string ( ) , v) ;
300303 }
301304 }
302-
303- if let Some ( v) = dict. remove ( "odyssey" ) {
304- dict. insert ( "odyssey" . to_string ( ) , v) ;
305- }
306305 map. insert ( profile, dict) ;
307306 }
308307 Ok ( map)
309308 }
309+
310+ fn profile ( & self ) -> Option < Profile > {
311+ self . 0 . profile ( )
312+ }
310313}
311314
312315/// A provider that sets the `src` and `output` path depending on their existence.
@@ -474,13 +477,15 @@ impl<P: Provider> Provider for RenameProfileProvider<P> {
474477 fn metadata ( & self ) -> Metadata {
475478 self . provider . metadata ( )
476479 }
480+
477481 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
478482 let mut data = self . provider . data ( ) ?;
479483 if let Some ( data) = data. remove ( & self . from ) {
480484 return Ok ( Map :: from ( [ ( self . to . clone ( ) , data) ] ) ) ;
481485 }
482486 Ok ( Default :: default ( ) )
483487 }
488+
484489 fn profile ( & self ) -> Option < Profile > {
485490 Some ( self . to . clone ( ) )
486491 }
@@ -517,31 +522,32 @@ impl<P: Provider> Provider for UnwrapProfileProvider<P> {
517522 fn metadata ( & self ) -> Metadata {
518523 self . provider . metadata ( )
519524 }
525+
520526 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
521- self . provider . data ( ) . and_then ( |mut data| {
522- if let Some ( profiles) = data. remove ( & self . wrapping_key ) {
523- for ( profile_str, profile_val) in profiles {
524- let profile = Profile :: new ( & profile_str) ;
525- if profile != self . profile {
526- continue ;
527- }
528- match profile_val {
529- Value :: Dict ( _, dict) => return Ok ( profile. collect ( dict) ) ,
530- bad_val => {
531- let mut err = Error :: from ( figment:: error:: Kind :: InvalidType (
532- bad_val. to_actual ( ) ,
533- "dict" . into ( ) ,
534- ) ) ;
535- err. metadata = Some ( self . provider . metadata ( ) ) ;
536- err. profile = Some ( self . profile . clone ( ) ) ;
537- return Err ( err) ;
538- }
527+ let mut data = self . provider . data ( ) ?;
528+ if let Some ( profiles) = data. remove ( & self . wrapping_key ) {
529+ for ( profile_str, profile_val) in profiles {
530+ let profile = Profile :: new ( & profile_str) ;
531+ if profile != self . profile {
532+ continue ;
533+ }
534+ match profile_val {
535+ Value :: Dict ( _, dict) => return Ok ( profile. collect ( dict) ) ,
536+ bad_val => {
537+ let mut err = Error :: from ( figment:: error:: Kind :: InvalidType (
538+ bad_val. to_actual ( ) ,
539+ "dict" . into ( ) ,
540+ ) ) ;
541+ err. metadata = Some ( self . provider . metadata ( ) ) ;
542+ err. profile = Some ( self . profile . clone ( ) ) ;
543+ return Err ( err) ;
539544 }
540545 }
541546 }
542- Ok ( Default :: default ( ) )
543- } )
547+ }
548+ Ok ( Default :: default ( ) )
544549 }
550+
545551 fn profile ( & self ) -> Option < Profile > {
546552 Some ( self . profile . clone ( ) )
547553 }
@@ -578,15 +584,18 @@ impl<P: Provider> Provider for WrapProfileProvider<P> {
578584 fn metadata ( & self ) -> Metadata {
579585 self . provider . metadata ( )
580586 }
587+
581588 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
582589 if let Some ( inner) = self . provider . data ( ) ?. remove ( & self . profile ) {
583590 let value = Value :: from ( inner) ;
584- let dict = [ ( self . profile . to_string ( ) . to_snake_case ( ) , value) ] . into_iter ( ) . collect ( ) ;
591+ let mut dict = Dict :: new ( ) ;
592+ dict. insert ( self . profile . as_str ( ) . as_str ( ) . to_snake_case ( ) , value) ;
585593 Ok ( self . wrapping_key . collect ( dict) )
586594 } else {
587595 Ok ( Default :: default ( ) )
588596 }
589597 }
598+
590599 fn profile ( & self ) -> Option < Profile > {
591600 Some ( self . profile . clone ( ) )
592601 }
@@ -631,6 +640,7 @@ impl<P: Provider> Provider for OptionalStrictProfileProvider<P> {
631640 fn metadata ( & self ) -> Metadata {
632641 self . provider . metadata ( )
633642 }
643+
634644 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
635645 let mut figment = Figment :: from ( & self . provider ) ;
636646 for profile in & self . profiles {
@@ -651,6 +661,7 @@ impl<P: Provider> Provider for OptionalStrictProfileProvider<P> {
651661 err
652662 } )
653663 }
664+
654665 fn profile ( & self ) -> Option < Profile > {
655666 self . profiles . last ( ) . cloned ( )
656667 }
@@ -677,13 +688,11 @@ impl<P: Provider> Provider for FallbackProfileProvider<P> {
677688 }
678689
679690 fn data ( & self ) -> Result < Map < Profile , Dict > , Error > {
680- let data = self . provider . data ( ) ?;
681- if let Some ( fallback) = data. get ( & self . fallback ) {
682- let mut inner = data. get ( & self . profile ) . cloned ( ) . unwrap_or_default ( ) ;
691+ let mut data = self . provider . data ( ) ?;
692+ if let Some ( fallback) = data. remove ( & self . fallback ) {
693+ let mut inner = data. remove ( & self . profile ) . unwrap_or_default ( ) ;
683694 for ( k, v) in fallback {
684- if !inner. contains_key ( k) {
685- inner. insert ( k. to_owned ( ) , v. clone ( ) ) ;
686- }
695+ inner. entry ( k) . or_insert ( v) ;
687696 }
688697 Ok ( self . profile . collect ( inner) )
689698 } else {
0 commit comments