api-client-macro 0.1.4

Declaratively express a REST API client
Documentation
macro_rules! rest_method {
    (
        #[$method:ident $url:literal]
        $function:tt($($param:ident : $type:ty),*)
    ) => {
        #[allow(dead_code)]
        pub $function(&self $(,$param: &str)*) -> reqwest::RequestBuilder {
            let url = format!(concat!("{}/", $($url),*), self.base_url $(, $param)*);
            println!("{} {}", stringify!([<$method:upper>]), &url);
            self.client.$method(&url)
        }
    };
}

macro_rules! generate {
    ($client_type:ident, {
        $(
            $resource:ident {
                $(
                    #[$method:ident $url:literal]
                    $function:ident($($param:ident : $type:ty),*)
                ),* $(,)?

            }
        ),* $(,)?
    }) => {
        paste::paste! {
            mod internal {
                pub struct [<$client_type Builder>]<T> {
                    pub(crate) base_url: String,
                    pub(crate) client: T,
                }

                impl<T> [<$client_type Builder>]<T> where T: Default {
                    pub fn new(base_url: &str, client: Option<T>) -> Self {
                        Self {
                            base_url: base_url.to_string(),
                            client: client.unwrap_or_default(),
                        }
                    }
                }
            }

            pub mod blocking {
                use super::internal::*;

                pub type Client = reqwest::blocking::Client;
                pub type Builder = [<$client_type Builder>]<Client>;

                pub fn new(base_url: &str, client: Option<Client>) -> Builder {
                    Builder::new(base_url, client)
                }

                impl Builder {
                    $(
                        $(
                            #[allow(dead_code)]
                            pub fn [<$resource _ $function>](&self $(,$param: $type)*) -> reqwest::blocking::RequestBuilder {
                                let url = format!(concat!("{}/", $url), self.base_url $(, $param )*);
                                println!("{} {}", stringify!([<$method:upper>]), &url);
                                self.client.$method(&url)
                            }
                        )*
                    )*
                }
            }

            pub mod asynchronous {
                use super::internal::*;

                pub type Client = reqwest::Client;
                pub type Builder = [<$client_type Builder>]<Client>;

                pub fn new(base_url: &str, client: Option<Client>) -> Builder {
                    Builder::new(base_url, client)
                }

                impl Builder {
                    $(
                        $(
                            #[allow(dead_code)]
                            pub async fn [<$resource _ $function>](&self $(,$param: $type)*) -> reqwest::RequestBuilder {
                                let url = format!(concat!("{}/", $url), self.base_url $(, $param )*);
                                println!("{} {}", stringify!([<$method:upper>]), &url);
                                self.client.$method(&url)
                            }
                        )*
                    )*
                }
            }
        }
    };
}

generate!(BigQuery, {
    jobs {
        #[post "queries"]
        query(),

        #[get "jobs/{}"]
        get(id: &str),
    },
    tables {
        #[get "datasets/{}/tables"]
        list(dataset_id: &str),
    },
    tabledata {
        #[post "datasets/{}/tables/{}/insertAll"]
        insert_all(dataset_id: &str, table_id: &str),
    }
});

/* generate!(BigQuery, {
    jobs {
        post "bigquery/v2/projects/{project_id}/queries": query(project_id: &str),
        get "bigquery/v2/projects/{project_id}/jobs/{job_id}": get(project_id: &str, job_id: &str),
        get "bigquery/v2/projects/{project_id}/jobs?parentJobId={parent_job_id}&allUsers={all_users}": list(project_id: &str, parent_job_id: Option<&str>, all_users: Option<bool>)
    },
    tables {
        get "bigquery/v2/projects/{project_id}/datasets/{dataset_id}/tables": list(project_id: &str, dataset_id: &str)
    },
    tabledata {
        post "bigquery/v2/projects/{project_id}/datasets/{dataset_id}/tables/{table_id}/insertAll": insert_all(project_id: &str, dataset_id: &str, table_id: &str)
    }
}); */

/* generate!(BigQuery, {
    jobs {
        post bigquery/v2/projects/{project_id: &str}/queries: query,
        get bigquery/v2/projects/{project_id: &str}/jobs/{job_id: &str}: get
    },
    tables {
        get bigquery/v2/projects/{project_id: &str}/datasets/{dataset_id: &str}/tables: list
    },
    tabledata {
        post bigquery/v2/projects/{project_id: &str}/datasets/{dataset_id: &str}/tables/{table_id: &str}/insertAll: insert_all
    }
}); */

fn main() {
    let blocking_client = blocking::new("base_url", None);
    blocking_client.jobs_query();
    blocking_client.jobs_get("job_id");
    blocking_client.tables_list("dataset_id");
    //blocking_client.jobs_list("", None, None);
}