@@ -12,6 +12,8 @@ pub enum YamlError {
12
12
NotVec ( Yaml ) ,
13
13
#[ error( "Value is not a string: {0:?}" ) ]
14
14
NotStr ( Yaml ) ,
15
+ #[ error( "Value is not a supported hash key: {0:?}" ) ]
16
+ NotKey ( Yaml ) ,
15
17
#[ error( "Value is not integer: {0:?}" ) ]
16
18
NotInt ( Yaml ) ,
17
19
#[ error( "Value is not boolean: {0:?}" ) ]
@@ -23,6 +25,7 @@ pub trait AsType {
23
25
fn hash ( & self ) -> Result < & Hash , YamlError > ;
24
26
fn vec ( & self ) -> Result < & Vec < Yaml > , YamlError > ;
25
27
fn str ( & self ) -> Result < & str , YamlError > ;
28
+ fn key ( & self ) -> Result < & str , YamlError > ;
26
29
fn i64 ( & self ) -> Result < i64 , YamlError > ;
27
30
fn bool ( & self ) -> Result < bool , YamlError > ;
28
31
}
@@ -44,6 +47,19 @@ impl AsType for Yaml {
44
47
fn str ( & self ) -> Result < & str , YamlError > {
45
48
self . as_str ( ) . ok_or_else ( || YamlError :: NotStr ( self . clone ( ) ) )
46
49
}
50
+ fn key ( & self ) -> Result < & str , YamlError > {
51
+ match self {
52
+ Yaml :: String ( k) => Ok ( k) ,
53
+ Yaml :: Array ( a) if matches ! ( a. as_slice( ) , [ Yaml :: String ( _) , Yaml :: Integer ( _) ] ) => {
54
+ if let [ Yaml :: String ( k) , Yaml :: Integer ( _) ] = a. as_slice ( ) {
55
+ Ok ( k)
56
+ } else {
57
+ unreachable ! ( )
58
+ }
59
+ }
60
+ _ => Err ( YamlError :: NotKey ( self . clone ( ) ) ) ,
61
+ }
62
+ }
47
63
fn i64 ( & self ) -> Result < i64 , YamlError > {
48
64
parse_i64 ( self ) . ok_or_else ( || YamlError :: NotInt ( self . clone ( ) ) )
49
65
}
@@ -148,26 +164,29 @@ impl<'a> Iterator for OverStringIter<'a> {
148
164
149
165
type HashIter < ' a > = OptIter < linked_hash_map:: Iter < ' a , Yaml , Yaml > > ;
150
166
151
- pub trait GetVal {
152
- fn get_bool ( & self , k : & str ) -> Result < Option < bool > > ;
153
- fn get_i64 ( & self , k : & str ) -> Result < Option < i64 > > ;
154
- fn get_u64 ( & self , k : & str ) -> Result < Option < u64 > > {
167
+ pub trait GetVal < K >
168
+ where
169
+ K : ?Sized ,
170
+ {
171
+ fn get_bool ( & self , k : & K ) -> Result < Option < bool > > ;
172
+ fn get_i64 ( & self , k : & K ) -> Result < Option < i64 > > ;
173
+ fn get_u64 ( & self , k : & K ) -> Result < Option < u64 > > {
155
174
self . get_i64 ( k) . map ( |v| v. map ( |v| v as u64 ) )
156
175
}
157
- fn get_u32 ( & self , k : & str ) -> Result < Option < u32 > > {
176
+ fn get_u32 ( & self , k : & K ) -> Result < Option < u32 > > {
158
177
self . get_i64 ( k) . map ( |v| v. map ( |v| v as u32 ) )
159
178
}
160
- fn get_str ( & self , k : & str ) -> Result < Option < & str > > ;
161
- fn get_string ( & self , k : & str ) -> Result < Option < String > > {
179
+ fn get_str ( & self , k : & K ) -> Result < Option < & str > > ;
180
+ fn get_string ( & self , k : & K ) -> Result < Option < String > > {
162
181
self . get_str ( k) . map ( |v| v. map ( From :: from) )
163
182
}
164
- fn get_hash ( & self , k : & str ) -> Result < Option < & Hash > > ;
165
- fn hash_iter < ' a > ( & ' a self , k : & str ) -> HashIter < ' a > ;
166
- fn get_vec ( & self , k : & str ) -> Result < Option < & Vec < Yaml > > > ;
167
- fn str_vec_iter < ' a > ( & ' a self , k : & str ) -> Result < OptIter < OverStringIter < ' a > > > ;
183
+ fn get_hash ( & self , k : & K ) -> Result < Option < & Hash > > ;
184
+ fn hash_iter < ' a > ( & ' a self , k : & K ) -> HashIter < ' a > ;
185
+ fn get_vec ( & self , k : & K ) -> Result < Option < & Vec < Yaml > > > ;
186
+ fn str_vec_iter < ' a > ( & ' a self , k : & K ) -> Result < OptIter < OverStringIter < ' a > > > ;
168
187
}
169
188
170
- impl GetVal for Hash {
189
+ impl GetVal < str > for Hash {
171
190
fn get_bool ( & self , k : & str ) -> Result < Option < bool > > {
172
191
match self . get ( & k. to_yaml ( ) ) {
173
192
None => Ok ( None ) ,
@@ -230,3 +249,63 @@ impl GetVal for Hash {
230
249
} ) )
231
250
}
232
251
}
252
+
253
+ impl GetVal < Yaml > for Hash {
254
+ fn get_bool ( & self , k : & Yaml ) -> Result < Option < bool > > {
255
+ match self . get ( k) {
256
+ None => Ok ( None ) ,
257
+ Some ( v) => v
258
+ . bool ( )
259
+ . with_context ( || format ! ( "Under key `{k:?}`" ) )
260
+ . map ( Some ) ,
261
+ }
262
+ }
263
+ fn get_i64 ( & self , k : & Yaml ) -> Result < Option < i64 > > {
264
+ match self . get ( k) {
265
+ None => Ok ( None ) ,
266
+ Some ( v) => v
267
+ . i64 ( )
268
+ . with_context ( || format ! ( "Under key `{k:?}`" ) )
269
+ . map ( Some ) ,
270
+ }
271
+ }
272
+ fn get_str ( & self , k : & Yaml ) -> Result < Option < & str > > {
273
+ match self . get ( k) {
274
+ None => Ok ( None ) ,
275
+ Some ( v) => v
276
+ . str ( )
277
+ . with_context ( || format ! ( "Under key `{k:?}`" ) )
278
+ . map ( Some ) ,
279
+ }
280
+ }
281
+ fn get_hash ( & self , k : & Yaml ) -> Result < Option < & Hash > > {
282
+ match self . get ( k) {
283
+ None => Ok ( None ) ,
284
+ Some ( v) => v
285
+ . hash ( )
286
+ . with_context ( || format ! ( "Under key `{k:?}`" ) )
287
+ . map ( Some ) ,
288
+ }
289
+ }
290
+ fn hash_iter < ' a > ( & ' a self , k : & Yaml ) -> HashIter < ' a > {
291
+ HashIter :: new ( self . get ( k) . and_then ( Yaml :: as_hash) . map ( |h| h. iter ( ) ) )
292
+ }
293
+ fn get_vec ( & self , k : & Yaml ) -> Result < Option < & Vec < Yaml > > > {
294
+ match self . get ( k) {
295
+ None => Ok ( None ) ,
296
+ Some ( v) => v
297
+ . vec ( )
298
+ . with_context ( || format ! ( "Under key `{k:?}`" ) )
299
+ . map ( Some ) ,
300
+ }
301
+ }
302
+ fn str_vec_iter < ' a > ( & ' a self , k : & Yaml ) -> Result < OptIter < OverStringIter < ' a > > > {
303
+ Ok ( OptIter :: new ( match self . get ( k) {
304
+ None => None ,
305
+ Some ( y) if matches ! ( y, Yaml :: String ( _) | Yaml :: Array ( _) ) => {
306
+ Some ( OverStringIter ( y, None ) )
307
+ }
308
+ _ => return Err ( anyhow ! ( "`{k:?}` requires string value or array of strings" ) ) ,
309
+ } ) )
310
+ }
311
+ }
0 commit comments