diff --git a/Cargo.toml b/Cargo.toml index c69646f68..29dd88770 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ description = "A partial oauth2 implementation, providing the 'device' authoriza documentation = "http://byron.github.io/yup-oauth2" keywords = ["google", "oauth", "v2"] license = "MIT" +build = "build.rs" [dependencies] chrono = "*" @@ -18,7 +19,16 @@ url = "*" hyper = ">= 0.5.0" itertools = "*" serde = "*" -serde_macros = "*" +serde_macros = { version = "*", optional = true } + +[features] +default = ["with_syntex"] +nightly = ["serde_macros"] +with_syntex = ["serde_codegen", "syntex"] + +[build-dependencies] +syntex = { version = "*", optional = true } +serde_codegen = { version = "*", optional = true } [dev-dependencies] getopts = "*" diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..2525f958f --- /dev/null +++ b/build.rs @@ -0,0 +1,28 @@ +#[cfg(feature = "with_syntex")] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("src/lib.rs.in"); + let dst = Path::new(&out_dir).join("lib.rs"); + + let mut registry = syntex::Registry::new(); + serde_codegen::register(&mut registry); + registry.expand("yup-oauth2", &src, &dst).unwrap(); + } +} + +#[cfg(not(feature = "with_syntex"))] +mod inner { + pub fn main() {} +} + +pub fn main() { + inner::main() +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9f43bf385..2e0e0155b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,89 +1,10 @@ -//! This library can be used to acquire oauth2.0 authentication for services. -//! At the time of writing, only one way of doing so is implemented, the [device flow](https://developers.google.com/youtube/v3/guides/authentication#devices), along with a flow -//! for [refreshing tokens](https://developers.google.com/youtube/v3/guides/authentication#devices) -//! -//! For your application to use this library, you will have to obtain an application -//! id and secret by [following this guide](https://developers.google.com/youtube/registering_an_application). -//! -//! # Device Flow Usage -//! As the `DeviceFlow` involves polling, the `DeviceFlowHelper` should be used -//! as means to adhere to the protocol, and remain resilient to all kinds of errors -//! that can occour on the way. -//! -//! The returned `Token` should be stored permanently to authorize future API requests. -//! -//! ```test_harness,no_run -//! #![feature(custom_derive, plugin)] -//! #![plugin(serde_macros)] -//! extern crate hyper; -//! extern crate yup_oauth2 as oauth2; -//! extern crate serde; -//! -//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken}; -//! use serde::json; -//! use std::default::Default; -//! # const SECRET: &'static str = "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}"; -//! -//! # #[test] fn device() { -//! let secret = json::from_str::(SECRET).unwrap().installed.unwrap(); -//! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate, -//! hyper::Client::new(), -//! ::default(), None) -//! .token(&["https://www.googleapis.com/auth/youtube.upload"]); -//! match res { -//! Ok(t) => { -//! // now you can use t.access_token to authenticate API calls within your -//! // given scopes. It will not be valid forever, which is when you have to -//! // refresh it using the `RefreshFlow` -//! }, -//! Err(err) => println!("Failed to acquire token: {}", err), -//! } -//! # } -//! ``` -//! -//! # Refresh Flow Usage -//! As the `Token` you retrieved previously will only be valid for a certain time, you will have -//! to use the information from the `Token.refresh_token` field to get a new `access_token`. -//! -//! ```test_harness,no_run -//! extern crate hyper; -//! extern crate yup_oauth2 as oauth2; -//! use oauth2::{RefreshFlow, FlowType, RefreshResult}; -//! -//! # #[test] fn refresh() { -//! let mut f = RefreshFlow::new(hyper::Client::new()); -//! let new_token = match *f.refresh_token(FlowType::Device, -//! "my_client_id", "my_secret", -//! "my_refresh_token") { -//! RefreshResult::Success(ref t) => t, -//! _ => panic!("bad luck ;)") -//! }; -//! # } -//! ``` -#![feature(custom_derive, plugin)] -#![plugin(serde_macros)] -extern crate chrono; +#[cfg_attr(feature = "nightly", feature(plugin))] +#[cfg_attr(feature = "nightly", plugin(serde_macros))] -#[macro_use] -extern crate hyper; -#[macro_use] -extern crate log; -#[cfg(test)] #[macro_use] -extern crate yup_hyper_mock as hyper_mock; -extern crate mime; -extern crate url; -extern crate time; -extern crate itertools; extern crate serde; +#[cfg(feature = "nightly")] +include!("lib.rs.in"); -mod device; -mod refresh; -mod common; -mod helper; - -pub use device::{DeviceFlow, PollInformation, PollError}; -pub use refresh::{RefreshFlow, RefreshResult}; -pub use common::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType}; -pub use helper::{TokenStorage, NullStorage, MemoryStorage, Authenticator, - AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate, GetToken}; +#[cfg(feature = "with_syntex")] +include!(concat!(env!("OUT_DIR"), "/lib.rs")); \ No newline at end of file diff --git a/src/lib.rs.in b/src/lib.rs.in new file mode 100644 index 000000000..acce7a20d --- /dev/null +++ b/src/lib.rs.in @@ -0,0 +1,87 @@ +//! This library can be used to acquire oauth2.0 authentication for services. +//! At the time of writing, only one way of doing so is implemented, the [device flow](https://developers.google.com/youtube/v3/guides/authentication#devices), along with a flow +//! for [refreshing tokens](https://developers.google.com/youtube/v3/guides/authentication#devices) +//! +//! For your application to use this library, you will have to obtain an application +//! id and secret by [following this guide](https://developers.google.com/youtube/registering_an_application). +//! +//! # Device Flow Usage +//! As the `DeviceFlow` involves polling, the `DeviceFlowHelper` should be used +//! as means to adhere to the protocol, and remain resilient to all kinds of errors +//! that can occour on the way. +//! +//! The returned `Token` should be stored permanently to authorize future API requests. +//! +//! ```test_harness,no_run +//! #![feature(custom_derive, plugin)] +//! #![plugin(serde_macros)] +//! extern crate hyper; +//! extern crate yup_oauth2 as oauth2; +//! extern crate serde; +//! +//! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, PollInformation, ConsoleApplicationSecret, MemoryStorage, GetToken}; +//! use serde::json; +//! use std::default::Default; +//! # const SECRET: &'static str = "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}"; +//! +//! # #[test] fn device() { +//! let secret = json::from_str::(SECRET).unwrap().installed.unwrap(); +//! let res = Authenticator::new(&secret, DefaultAuthenticatorDelegate, +//! hyper::Client::new(), +//! ::default(), None) +//! .token(&["https://www.googleapis.com/auth/youtube.upload"]); +//! match res { +//! Ok(t) => { +//! // now you can use t.access_token to authenticate API calls within your +//! // given scopes. It will not be valid forever, which is when you have to +//! // refresh it using the `RefreshFlow` +//! }, +//! Err(err) => println!("Failed to acquire token: {}", err), +//! } +//! # } +//! ``` +//! +//! # Refresh Flow Usage +//! As the `Token` you retrieved previously will only be valid for a certain time, you will have +//! to use the information from the `Token.refresh_token` field to get a new `access_token`. +//! +//! ```test_harness,no_run +//! extern crate hyper; +//! extern crate yup_oauth2 as oauth2; +//! use oauth2::{RefreshFlow, FlowType, RefreshResult}; +//! +//! # #[test] fn refresh() { +//! let mut f = RefreshFlow::new(hyper::Client::new()); +//! let new_token = match *f.refresh_token(FlowType::Device, +//! "my_client_id", "my_secret", +//! "my_refresh_token") { +//! RefreshResult::Success(ref t) => t, +//! _ => panic!("bad luck ;)") +//! }; +//! # } +//! ``` +extern crate chrono; + +#[macro_use] +extern crate hyper; +#[macro_use] +extern crate log; +#[cfg(test)] #[macro_use] +extern crate yup_hyper_mock as hyper_mock; +extern crate mime; +extern crate url; +extern crate time; +extern crate itertools; +extern crate serde; + + +mod device; +mod refresh; +mod common; +mod helper; + +pub use device::{DeviceFlow, PollInformation, PollError}; +pub use refresh::{RefreshFlow, RefreshResult}; +pub use common::{Token, FlowType, ApplicationSecret, ConsoleApplicationSecret, Scheme, TokenType}; +pub use helper::{TokenStorage, NullStorage, MemoryStorage, Authenticator, + AuthenticatorDelegate, Retry, DefaultAuthenticatorDelegate, GetToken};