@@ -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