@@ -12,6 +12,8 @@ pub enum YamlError {
1212 NotVec ( Yaml ) ,
1313 #[ error( "Value is not a string: {0:?}" ) ]
1414 NotStr ( Yaml ) ,
15+ #[ error( "Value is not a supported hash key: {0:?}" ) ]
16+ NotKey ( Yaml ) ,
1517 #[ error( "Value is not integer: {0:?}" ) ]
1618 NotInt ( Yaml ) ,
1719 #[ error( "Value is not boolean: {0:?}" ) ]
@@ -23,6 +25,7 @@ pub trait AsType {
2325 fn hash ( & self ) -> Result < & Hash , YamlError > ;
2426 fn vec ( & self ) -> Result < & Vec < Yaml > , YamlError > ;
2527 fn str ( & self ) -> Result < & str , YamlError > ;
28+ fn key ( & self ) -> Result < & str , YamlError > ;
2629 fn i64 ( & self ) -> Result < i64 , YamlError > ;
2730 fn bool ( & self ) -> Result < bool , YamlError > ;
2831}
@@ -44,6 +47,19 @@ impl AsType for Yaml {
4447 fn str ( & self ) -> Result < & str , YamlError > {
4548 self . as_str ( ) . ok_or_else ( || YamlError :: NotStr ( self . clone ( ) ) )
4649 }
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+ }
4763 fn i64 ( & self ) -> Result < i64 , YamlError > {
4864 parse_i64 ( self ) . ok_or_else ( || YamlError :: NotInt ( self . clone ( ) ) )
4965 }
@@ -148,26 +164,29 @@ impl<'a> Iterator for OverStringIter<'a> {
148164
149165type HashIter < ' a > = OptIter < linked_hash_map:: Iter < ' a , Yaml , Yaml > > ;
150166
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 > > {
155174 self . get_i64 ( k) . map ( |v| v. map ( |v| v as u64 ) )
156175 }
157- fn get_u32 ( & self , k : & str ) -> Result < Option < u32 > > {
176+ fn get_u32 ( & self , k : & K ) -> Result < Option < u32 > > {
158177 self . get_i64 ( k) . map ( |v| v. map ( |v| v as u32 ) )
159178 }
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 > > {
162181 self . get_str ( k) . map ( |v| v. map ( From :: from) )
163182 }
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 > > > ;
168187}
169188
170- impl GetVal for Hash {
189+ impl GetVal < str > for Hash {
171190 fn get_bool ( & self , k : & str ) -> Result < Option < bool > > {
172191 match self . get ( & k. to_yaml ( ) ) {
173192 None => Ok ( None ) ,
@@ -230,3 +249,63 @@ impl GetVal for Hash {
230249 } ) )
231250 }
232251}
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