@@ -34,7 +34,8 @@ use std::{
3434} ;
3535
3636#[ cfg( test) ]
37- use quote:: { ToTokens , Tokens } ;
37+ use quote:: ToTokens ;
38+ use quote:: Tokens ;
3839use semver:: Version ;
3940use void:: Void ;
4041
@@ -63,9 +64,9 @@ pub struct Api {
6364 /// parameters that are common to all API methods
6465 pub common_params : BTreeMap < String , Type > ,
6566 /// root API methods e.g. Search, Index
66- pub root : BTreeMap < String , ApiEndpoint > ,
67+ pub root : ApiNamespace ,
6768 /// namespace client methods e.g. Indices.Create, Ml.PutJob
68- pub namespaces : BTreeMap < String , BTreeMap < String , ApiEndpoint > > ,
69+ pub namespaces : BTreeMap < String , ApiNamespace > ,
6970 /// enums in parameters
7071 pub enums : Vec < ApiEnum > ,
7172}
@@ -79,9 +80,9 @@ impl Api {
7980 pub fn endpoint_for_api_call ( & self , api_call : & str ) -> Option < & ApiEndpoint > {
8081 let api_call_path: Vec < & str > = api_call. split ( '.' ) . collect ( ) ;
8182 match api_call_path. len ( ) {
82- 1 => self . root . get ( api_call_path[ 0 ] ) ,
83+ 1 => self . root . endpoints ( ) . get ( api_call_path[ 0 ] ) ,
8384 _ => match self . namespaces . get ( api_call_path[ 0 ] ) {
84- Some ( namespace) => namespace. get ( api_call_path[ 1 ] ) ,
85+ Some ( namespace) => namespace. endpoints ( ) . get ( api_call_path[ 1 ] ) ,
8586 None => None ,
8687 } ,
8788 }
@@ -347,13 +348,49 @@ where
347348 deserializer. deserialize_any ( StringOrStruct ( PhantomData ) )
348349}
349350
351+ /// Stability level of an API endpoint. Ordering defines increasing stability level, i.e.
352+ /// `beta` is "more stable" than `experimental`.
353+ #[ derive( Debug , Eq , PartialEq , Deserialize , Clone , Copy , Ord , PartialOrd ) ]
354+ pub enum Stability {
355+ #[ serde( rename = "experimental" ) ]
356+ Experimental ,
357+ #[ serde( rename = "beta" ) ]
358+ Beta ,
359+ #[ serde( rename = "stable" ) ]
360+ Stable ,
361+ }
362+
363+ impl Stability {
364+ pub fn feature_name ( self ) -> Option < & ' static str > {
365+ match self {
366+ Stability :: Experimental => Some ( "experimental-apis" ) ,
367+ Stability :: Beta => Some ( "beta-apis" ) ,
368+ Stability :: Stable => None ,
369+ }
370+ }
371+
372+ /// Returns the (optional) feature configuration for this stability level as an outer
373+ /// attribute, for use e.g. on function definitions.
374+ pub fn outer_cfg_attr ( self ) -> Option < Tokens > {
375+ let feature_name = self . feature_name ( ) ;
376+ feature_name. map ( |name| quote ! ( #[ cfg( feature = #name) ] ) )
377+ }
378+
379+ /// Returns the (optional) feature configuration for this stability level as an inner
380+ /// attribute, for use e.g. at the top of a module source file
381+ pub fn inner_cfg_attr ( self ) -> Option < Tokens > {
382+ let feature_name = self . feature_name ( ) ;
383+ feature_name. map ( |name| quote ! ( #![ cfg( feature = #name) ] ) )
384+ }
385+ }
386+
350387/// An API endpoint defined in the REST API specs
351388#[ derive( Debug , PartialEq , Deserialize , Clone ) ]
352389pub struct ApiEndpoint {
353390 pub full_name : Option < String > ,
354391 #[ serde( deserialize_with = "string_or_struct" ) ]
355392 documentation : Documentation ,
356- pub stability : String ,
393+ pub stability : Stability ,
357394 pub url : Url ,
358395 #[ serde( default = "BTreeMap::new" ) ]
359396 pub params : BTreeMap < String , Type > ,
@@ -382,6 +419,34 @@ impl ApiEndpoint {
382419 }
383420}
384421
422+ pub struct ApiNamespace {
423+ stability : Stability ,
424+ endpoints : BTreeMap < String , ApiEndpoint > ,
425+ }
426+
427+ impl ApiNamespace {
428+ pub fn new ( ) -> Self {
429+ ApiNamespace {
430+ stability : Stability :: Experimental , // will grow in stability as we add endpoints
431+ endpoints : BTreeMap :: new ( ) ,
432+ }
433+ }
434+
435+ pub fn add ( & mut self , name : String , endpoint : ApiEndpoint ) {
436+ // Stability of a namespace is that of the most stable of its endpoints
437+ self . stability = Stability :: max ( self . stability , endpoint. stability ) ;
438+ self . endpoints . insert ( name, endpoint) ;
439+ }
440+
441+ pub fn stability ( & self ) -> Stability {
442+ self . stability
443+ }
444+
445+ pub fn endpoints ( & self ) -> & BTreeMap < String , ApiEndpoint > {
446+ & self . endpoints
447+ }
448+ }
449+
385450/// Common parameters accepted by all API endpoints
386451#[ derive( Debug , PartialEq , Deserialize , Clone ) ]
387452pub struct Common {
@@ -396,6 +461,7 @@ pub struct ApiEnum {
396461 pub name : String ,
397462 pub description : Option < String > ,
398463 pub values : Vec < String > ,
464+ pub stability : Stability , // inherited from the declaring API
399465}
400466
401467impl Hash for ApiEnum {
@@ -499,7 +565,7 @@ pub use bulk::*;
499565/// Reads Api from a directory of REST Api specs
500566pub fn read_api ( branch : & str , download_dir : & PathBuf ) -> Result < Api , failure:: Error > {
501567 let paths = fs:: read_dir ( download_dir) ?;
502- let mut namespaces = BTreeMap :: new ( ) ;
568+ let mut namespaces = BTreeMap :: < String , ApiNamespace > :: new ( ) ;
503569 let mut enums: HashSet < ApiEnum > = HashSet :: new ( ) ;
504570 let mut common_params = BTreeMap :: new ( ) ;
505571 let root_key = "root" ;
@@ -517,11 +583,6 @@ pub fn read_api(branch: &str, download_dir: &PathBuf) -> Result<Api, failure::Er
517583 let mut file = File :: open ( & path) ?;
518584 let ( name, api_endpoint) = endpoint_from_file ( display, & mut file) ?;
519585
520- // Only generate builders and methods for stable APIs, not experimental or beta
521- if & api_endpoint. stability != "stable" {
522- continue ;
523- }
524-
525586 let name_parts: Vec < & str > = name. splitn ( 2 , '.' ) . collect ( ) ;
526587 let ( namespace, method_name) = match name_parts. len ( ) {
527588 len if len > 1 => ( name_parts[ 0 ] . to_string ( ) , name_parts[ 1 ] . to_string ( ) ) ,
@@ -545,19 +606,20 @@ pub fn read_api(branch: &str, download_dir: &PathBuf) -> Result<Api, failure::Er
545606 name : param. 0 . to_string ( ) ,
546607 description : param. 1 . description . clone ( ) ,
547608 values : options,
609+ stability : api_endpoint. stability ,
548610 } ) ;
549611 }
550612
551613 // collect api endpoints into namespaces
552614 if !namespaces. contains_key ( & namespace) {
553- let mut api_endpoints = BTreeMap :: new ( ) ;
554- api_endpoints . insert ( method_name, api_endpoint) ;
555- namespaces. insert ( namespace. to_string ( ) , api_endpoints ) ;
615+ let mut api_namespace = ApiNamespace :: new ( ) ;
616+ api_namespace . add ( method_name, api_endpoint) ;
617+ namespaces. insert ( namespace. to_string ( ) , api_namespace ) ;
556618 } else {
557619 namespaces
558620 . get_mut ( & namespace)
559621 . unwrap ( )
560- . insert ( method_name, api_endpoint) ;
622+ . add ( method_name, api_endpoint) ;
561623 }
562624 } else if name
563625 . map ( |name| name == Some ( "_common.json" ) )
@@ -627,3 +689,14 @@ where
627689pub fn ast_eq < T : ToTokens > ( expected : Tokens , actual : T ) {
628690 assert_eq ! ( expected, quote!( #actual) ) ;
629691}
692+
693+ #[ cfg( test) ]
694+ mod tests {
695+ use super :: * ;
696+
697+ #[ test]
698+ fn stability_ordering ( ) {
699+ assert ! ( Stability :: Beta > Stability :: Experimental ) ;
700+ assert ! ( Stability :: Stable > Stability :: Beta ) ;
701+ }
702+ }
0 commit comments