@@ -2155,6 +2155,12 @@ impl From<anyhow::Error> for ConfigError {
2155
2155
}
2156
2156
}
2157
2157
2158
+ #[ derive( Debug ) ]
2159
+ enum KeyOrIdx {
2160
+ Key ( String ) ,
2161
+ Idx ( usize ) ,
2162
+ }
2163
+
2158
2164
#[ derive( Eq , PartialEq , Clone ) ]
2159
2165
pub enum ConfigValue {
2160
2166
Integer ( i64 , Definition ) ,
@@ -2197,26 +2203,56 @@ impl ConfigValue {
2197
2203
}
2198
2204
2199
2205
fn from_toml ( def : Definition , toml : toml:: Value ) -> CargoResult < ConfigValue > {
2206
+ let mut error_path = Vec :: new ( ) ;
2207
+ Self :: from_toml_inner ( def, toml, & mut error_path) . with_context ( || {
2208
+ let mut it = error_path. iter ( ) . rev ( ) . peekable ( ) ;
2209
+ let mut key_path = String :: with_capacity ( error_path. len ( ) * 3 ) ;
2210
+ while let Some ( k) = it. next ( ) {
2211
+ match k {
2212
+ KeyOrIdx :: Key ( s) => key_path. push_str ( & key:: escape_key_part ( & s) ) ,
2213
+ KeyOrIdx :: Idx ( i) => key_path. push_str ( & format ! ( "[{i}]" ) ) ,
2214
+ }
2215
+ if matches ! ( it. peek( ) , Some ( KeyOrIdx :: Key ( _) ) ) {
2216
+ key_path. push ( '.' ) ;
2217
+ }
2218
+ }
2219
+ format ! ( "failed to parse config at `{key_path}`" )
2220
+ } )
2221
+ }
2222
+
2223
+ fn from_toml_inner (
2224
+ def : Definition ,
2225
+ toml : toml:: Value ,
2226
+ path : & mut Vec < KeyOrIdx > ,
2227
+ ) -> CargoResult < ConfigValue > {
2200
2228
match toml {
2201
2229
toml:: Value :: String ( val) => Ok ( CV :: String ( val, def) ) ,
2202
2230
toml:: Value :: Boolean ( b) => Ok ( CV :: Boolean ( b, def) ) ,
2203
2231
toml:: Value :: Integer ( i) => Ok ( CV :: Integer ( i, def) ) ,
2204
2232
toml:: Value :: Array ( val) => Ok ( CV :: List (
2205
2233
val. into_iter ( )
2206
- . map ( |toml| match toml {
2234
+ . enumerate ( )
2235
+ . map ( |( i, toml) | match toml {
2207
2236
toml:: Value :: String ( val) => Ok ( ( val, def. clone ( ) ) ) ,
2208
- v => bail ! ( "expected string but found {} in list" , v. type_str( ) ) ,
2237
+ v => {
2238
+ path. push ( KeyOrIdx :: Idx ( i) ) ;
2239
+ bail ! ( "expected string but found {} in list" , v. type_str( ) )
2240
+ }
2209
2241
} )
2210
2242
. collect :: < CargoResult < _ > > ( ) ?,
2211
2243
def,
2212
2244
) ) ,
2213
2245
toml:: Value :: Table ( val) => Ok ( CV :: Table (
2214
2246
val. into_iter ( )
2215
- . map ( |( key, value) | {
2216
- let value = CV :: from_toml ( def. clone ( ) , value)
2217
- . with_context ( || format ! ( "failed to parse key `{}`" , key) ) ?;
2218
- Ok ( ( key, value) )
2219
- } )
2247
+ . map (
2248
+ |( key, value) | match CV :: from_toml_inner ( def. clone ( ) , value, path) {
2249
+ Ok ( value) => Ok ( ( key, value) ) ,
2250
+ Err ( e) => {
2251
+ path. push ( KeyOrIdx :: Key ( key) ) ;
2252
+ Err ( e)
2253
+ }
2254
+ } ,
2255
+ )
2220
2256
. collect :: < CargoResult < _ > > ( ) ?,
2221
2257
def,
2222
2258
) ) ,
0 commit comments