diff --git a/Cargo.toml b/Cargo.toml index 632a0a6..3928881 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,13 +12,19 @@ documentation = "https://cmcenroe.me/inth-oauth2/inth_oauth2" repository = "https://github.com/programble/inth-oauth2" readme = "README.md" +[features] +default = ["serde"] + [dependencies] chrono = "0.2.17" hyper = "0.7.0" rustc-serialize = "0.3.16" -serde = "0.7.0" url = "0.5.0" +[dependencies.serde] +version = "0.7.0" +optional = true + [dev-dependencies] serde_json = "0.7.0" yup-hyper-mock = "1.3.2" diff --git a/src/lib.rs b/src/lib.rs index a0eae32..7faf8b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,7 +113,7 @@ //! ### Persisting tokens //! //! All token types implement `Encodable` / `Decodable` from `rustc_serialize` and `Serialize` / -//! `Deserialize` from `serde`. +//! `Deserialize` from `serde` (with the default `serde` feature). //! //! ```no_run //! # extern crate inth_oauth2; @@ -134,12 +134,15 @@ //! extern crate serde_json; //! # use inth_oauth2::Client; //! # use inth_oauth2::provider::google::Installed; +//! # #[cfg(feature = "serde")] //! # fn main() { //! # let http_client = Default::default(); //! # let client = Client::::new(String::new(), String::new(), None); //! # let token = client.request_token(&http_client, "").unwrap(); //! let json = serde_json::to_string(&token).unwrap(); //! # } +//! # #[cfg(not(feature = "serde"))] +//! # fn main() { } //! ``` #![warn( @@ -158,9 +161,11 @@ extern crate chrono; extern crate hyper; extern crate rustc_serialize; -extern crate serde; extern crate url; +#[cfg(feature = "serde")] +extern crate serde; + pub use token::{Token, Lifetime}; pub use client::{Client, ClientError}; @@ -169,5 +174,5 @@ pub mod provider; pub mod error; pub mod client; -#[cfg(test)] +#[cfg(all(test, feature = "serde"))] extern crate serde_json; diff --git a/src/token/bearer.rs b/src/token/bearer.rs index 48bade8..6cde937 100644 --- a/src/token/bearer.rs +++ b/src/token/bearer.rs @@ -1,9 +1,5 @@ -use std::marker::PhantomData; - use hyper::header; use rustc_serialize::json::Json; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use serde::{ser, de}; use super::{Token, Lifetime}; use client::response::{FromResponse, ParseError, JsonHelper}; @@ -62,93 +58,104 @@ impl FromResponse for Bearer { } } -impl Serialize for Bearer { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { - serializer.serialize_struct("Bearer", SerVisitor(self, 0)) - } -} +#[cfg(feature = "serde")] +mod serde { + use std::marker::PhantomData; -struct SerVisitor<'a, L: Lifetime + Serialize + 'a>(&'a Bearer, u8); -impl<'a, L: Lifetime + Serialize + 'a> ser::MapVisitor for SerVisitor<'a, L> { - fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { - self.1 += 1; - match self.1 { - 1 => serializer.serialize_struct_elt("access_token", &self.0.access_token).map(Some), - 2 => serializer.serialize_struct_elt("scope", &self.0.scope).map(Some), - 3 => serializer.serialize_struct_elt("lifetime", &self.0.lifetime).map(Some), - _ => Ok(None), + use serde::{Serialize, Serializer, Deserialize, Deserializer}; + use serde::{ser, de}; + + use token::Lifetime; + use super::Bearer; + + impl Serialize for Bearer { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.serialize_struct("Bearer", SerVisitor(self, 0)) } } - fn len(&self) -> Option { Some(3) } -} - -impl Deserialize for Bearer { - fn deserialize(deserializer: &mut D) -> Result { - static FIELDS: &'static [&'static str] = &["access_token", "scope", "lifetime"]; - deserializer.deserialize_struct("Bearer", FIELDS, DeVisitor(PhantomData)) - } -} - -struct DeVisitor(PhantomData); -impl de::Visitor for DeVisitor { - type Value = Bearer; - - fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> { - let mut access_token = None; - let mut scope = None; - let mut lifetime = None; - - loop { - match try!(visitor.visit_key()) { - Some(Field::AccessToken) => access_token = Some(try!(visitor.visit_value())), - Some(Field::Scope) => scope = Some(try!(visitor.visit_value())), - Some(Field::Lifetime) => lifetime = Some(try!(visitor.visit_value())), - None => break, + struct SerVisitor<'a, L: Lifetime + Serialize + 'a>(&'a Bearer, u8); + impl<'a, L: Lifetime + Serialize + 'a> ser::MapVisitor for SerVisitor<'a, L> { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { + self.1 += 1; + match self.1 { + 1 => serializer.serialize_struct_elt("access_token", &self.0.access_token).map(Some), + 2 => serializer.serialize_struct_elt("scope", &self.0.scope).map(Some), + 3 => serializer.serialize_struct_elt("lifetime", &self.0.lifetime).map(Some), + _ => Ok(None), } } - let access_token = match access_token { - Some(s) => s, - None => return visitor.missing_field("access_token"), - }; - let lifetime = match lifetime { - Some(l) => l, - None => return visitor.missing_field("lifetime"), - }; - - try!(visitor.end()); - - Ok(Bearer { - access_token: access_token, - scope: scope, - lifetime: lifetime, - }) + fn len(&self) -> Option { Some(3) } } -} -enum Field { - AccessToken, - Scope, - Lifetime, -} - -impl Deserialize for Field { - fn deserialize(deserializer: &mut D) -> Result { - deserializer.deserialize(FieldVisitor) + impl Deserialize for Bearer { + fn deserialize(deserializer: &mut D) -> Result { + static FIELDS: &'static [&'static str] = &["access_token", "scope", "lifetime"]; + deserializer.deserialize_struct("Bearer", FIELDS, DeVisitor(PhantomData)) + } } -} -struct FieldVisitor; -impl de::Visitor for FieldVisitor { - type Value = Field; + struct DeVisitor(PhantomData); + impl de::Visitor for DeVisitor { + type Value = Bearer; - fn visit_str(&mut self, value: &str) -> Result { - match value { - "access_token" => Ok(Field::AccessToken), - "scope" => Ok(Field::Scope), - "lifetime" => Ok(Field::Lifetime), - _ => Err(de::Error::custom("expected access_token, scope or lifetime")), + fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> { + let mut access_token = None; + let mut scope = None; + let mut lifetime = None; + + loop { + match try!(visitor.visit_key()) { + Some(Field::AccessToken) => access_token = Some(try!(visitor.visit_value())), + Some(Field::Scope) => scope = Some(try!(visitor.visit_value())), + Some(Field::Lifetime) => lifetime = Some(try!(visitor.visit_value())), + None => break, + } + } + + let access_token = match access_token { + Some(s) => s, + None => return visitor.missing_field("access_token"), + }; + let lifetime = match lifetime { + Some(l) => l, + None => return visitor.missing_field("lifetime"), + }; + + try!(visitor.end()); + + Ok(Bearer { + access_token: access_token, + scope: scope, + lifetime: lifetime, + }) + } + } + + enum Field { + AccessToken, + Scope, + Lifetime, + } + + impl Deserialize for Field { + fn deserialize(deserializer: &mut D) -> Result { + deserializer.deserialize(FieldVisitor) + } + } + + struct FieldVisitor; + impl de::Visitor for FieldVisitor { + type Value = Field; + + fn visit_str(&mut self, value: &str) -> Result { + match value { + "access_token" => Ok(Field::AccessToken), + "scope" => Ok(Field::Scope), + "lifetime" => Ok(Field::Lifetime), + _ => Err(de::Error::custom("expected access_token, scope or lifetime")), + } } } } @@ -157,7 +164,6 @@ impl de::Visitor for FieldVisitor { mod tests { use chrono::{UTC, Duration}; use rustc_serialize::json::Json; - use serde_json; use client::response::{FromResponse, ParseError}; use token::{Static, Refresh}; @@ -260,8 +266,11 @@ mod tests { assert!(refresh.expires() <= &(UTC::now() + Duration::seconds(3600))); } + #[cfg(feature = "serde")] #[test] fn serialize_deserialize() { + use serde_json; + let original = Bearer { access_token: String::from("foo"), scope: Some(String::from("bar")), diff --git a/src/token/expiring.rs b/src/token/expiring.rs index 2e29067..a18808a 100644 --- a/src/token/expiring.rs +++ b/src/token/expiring.rs @@ -1,8 +1,6 @@ use chrono::{DateTime, UTC, Duration, TimeZone}; use rustc_serialize::json::Json; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use serde::{ser, de}; use super::Lifetime; use client::response::{FromResponse, ParseError, JsonHelper}; @@ -71,77 +69,86 @@ impl Decodable for Expiring { } } -impl Serialize for Expiring { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { - serializer.serialize_struct("Expiring", SerVisitor(self, 0)) - } -} +#[cfg(feature = "serde")] +mod serde { + use chrono::{UTC, TimeZone}; + use serde::{Serialize, Serializer, Deserialize, Deserializer}; + use serde::{ser, de}; -struct SerVisitor<'a>(&'a Expiring, u8); -impl<'a> ser::MapVisitor for SerVisitor<'a> { - fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { - self.1 += 1; - match self.1 { - 1 => serializer.serialize_struct_elt("expires", &self.0.expires.timestamp()).map(Some), - _ => Ok(None), + use super::Expiring; + + impl Serialize for Expiring { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.serialize_struct("Expiring", SerVisitor(self, 0)) } } - fn len(&self) -> Option { Some(1) } -} - -impl Deserialize for Expiring { - fn deserialize(deserializer: &mut D) -> Result { - static FIELDS: &'static [&'static str] = &["expires"]; - deserializer.deserialize_struct("Expiring", FIELDS, DeVisitor) - } -} - -struct DeVisitor; -impl de::Visitor for DeVisitor { - type Value = Expiring; - - fn visit_map(&mut self, mut visitor: V) -> Result { - let mut expires = None; - - loop { - match try!(visitor.visit_key()) { - Some(Field::Expires) => expires = Some(try!(visitor.visit_value())), - None => break, + struct SerVisitor<'a>(&'a Expiring, u8); + impl<'a> ser::MapVisitor for SerVisitor<'a> { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { + self.1 += 1; + match self.1 { + 1 => serializer.serialize_struct_elt("expires", &self.0.expires.timestamp()).map(Some), + _ => Ok(None), } } - let expires = match expires { - Some(i) => UTC.timestamp(i, 0), - None => return visitor.missing_field("expires"), - }; - - try!(visitor.end()); - - Ok(Expiring { - expires: expires, - }) + fn len(&self) -> Option { Some(1) } } -} -enum Field { - Expires, -} - -impl Deserialize for Field { - fn deserialize(deserializer: &mut D) -> Result { - deserializer.deserialize(FieldVisitor) + impl Deserialize for Expiring { + fn deserialize(deserializer: &mut D) -> Result { + static FIELDS: &'static [&'static str] = &["expires"]; + deserializer.deserialize_struct("Expiring", FIELDS, DeVisitor) + } } -} -struct FieldVisitor; -impl de::Visitor for FieldVisitor { - type Value = Field; + struct DeVisitor; + impl de::Visitor for DeVisitor { + type Value = Expiring; - fn visit_str(&mut self, value: &str) -> Result { - match value { - "expires" => Ok(Field::Expires), - _ => Err(de::Error::custom("expected expires")), + fn visit_map(&mut self, mut visitor: V) -> Result { + let mut expires = None; + + loop { + match try!(visitor.visit_key()) { + Some(Field::Expires) => expires = Some(try!(visitor.visit_value())), + None => break, + } + } + + let expires = match expires { + Some(i) => UTC.timestamp(i, 0), + None => return visitor.missing_field("expires"), + }; + + try!(visitor.end()); + + Ok(Expiring { + expires: expires, + }) + } + } + + enum Field { + Expires, + } + + impl Deserialize for Field { + fn deserialize(deserializer: &mut D) -> Result { + deserializer.deserialize(FieldVisitor) + } + } + + struct FieldVisitor; + impl de::Visitor for FieldVisitor { + type Value = Field; + + fn visit_str(&mut self, value: &str) -> Result { + match value { + "expires" => Ok(Field::Expires), + _ => Err(de::Error::custom("expected expires")), + } } } } @@ -150,7 +157,6 @@ impl de::Visitor for FieldVisitor { mod tests { use chrono::{UTC, Duration, Timelike}; use rustc_serialize::json::{self, Json}; - use serde_json; use client::response::FromResponse; use super::Expiring; @@ -173,8 +179,11 @@ mod tests { assert_eq!(expiring, decoded); } + #[cfg(feature = "serde")] #[test] fn serialize_deserialize() { + use serde_json; + let original = Expiring { expires: UTC::now().with_nanosecond(0).unwrap(), }; diff --git a/src/token/refresh.rs b/src/token/refresh.rs index 2ffd6b9..62ef4b6 100644 --- a/src/token/refresh.rs +++ b/src/token/refresh.rs @@ -1,8 +1,6 @@ use chrono::{DateTime, UTC, Duration, TimeZone}; use rustc_serialize::json::Json; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use serde::{ser, de}; use super::Lifetime; use client::response::{FromResponse, ParseError, JsonHelper}; @@ -93,87 +91,96 @@ impl Decodable for Refresh { } } -impl Serialize for Refresh { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { - serializer.serialize_struct("Refresh", SerVisitor(self, 0)) - } -} +#[cfg(feature = "serde")] +mod serde { + use chrono::{UTC, TimeZone}; + use serde::{Serialize, Serializer, Deserialize, Deserializer}; + use serde::{ser, de}; -struct SerVisitor<'a>(&'a Refresh, u8); -impl<'a> ser::MapVisitor for SerVisitor<'a> { - fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { - self.1 += 1; - match self.1 { - 1 => serializer.serialize_struct_elt("refresh_token", &self.0.refresh_token).map(Some), - 2 => serializer.serialize_struct_elt("expires", &self.0.expires.timestamp()).map(Some), - _ => Ok(None), + use super::Refresh; + + impl Serialize for Refresh { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.serialize_struct("Refresh", SerVisitor(self, 0)) } } - fn len(&self) -> Option { Some(2) } -} - -impl Deserialize for Refresh { - fn deserialize(deserializer: &mut D) -> Result { - static FIELDS: &'static [&'static str] = &["refresh_token", "expires"]; - deserializer.deserialize_struct("Refresh", FIELDS, DeVisitor) - } -} - -struct DeVisitor; -impl de::Visitor for DeVisitor { - type Value = Refresh; - - fn visit_map(&mut self, mut visitor: V) -> Result { - let mut refresh_token = None; - let mut expires = None; - - loop { - match try!(visitor.visit_key()) { - Some(Field::RefreshToken) => refresh_token = Some(try!(visitor.visit_value())), - Some(Field::Expires) => expires = Some(try!(visitor.visit_value())), - None => break, + struct SerVisitor<'a>(&'a Refresh, u8); + impl<'a> ser::MapVisitor for SerVisitor<'a> { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> { + self.1 += 1; + match self.1 { + 1 => serializer.serialize_struct_elt("refresh_token", &self.0.refresh_token).map(Some), + 2 => serializer.serialize_struct_elt("expires", &self.0.expires.timestamp()).map(Some), + _ => Ok(None), } } - let refresh_token = match refresh_token { - Some(s) => s, - None => return visitor.missing_field("refresh_token"), - }; - let expires = match expires { - Some(i) => UTC.timestamp(i, 0), - None => return visitor.missing_field("expires"), - }; - - try!(visitor.end()); - - Ok(Refresh { - refresh_token: refresh_token, - expires: expires, - }) + fn len(&self) -> Option { Some(2) } } -} -enum Field { - RefreshToken, - Expires, -} - -impl Deserialize for Field { - fn deserialize(deserializer: &mut D) -> Result { - deserializer.deserialize(FieldVisitor) + impl Deserialize for Refresh { + fn deserialize(deserializer: &mut D) -> Result { + static FIELDS: &'static [&'static str] = &["refresh_token", "expires"]; + deserializer.deserialize_struct("Refresh", FIELDS, DeVisitor) + } } -} -struct FieldVisitor; -impl de::Visitor for FieldVisitor { - type Value = Field; + struct DeVisitor; + impl de::Visitor for DeVisitor { + type Value = Refresh; - fn visit_str(&mut self, value: &str) -> Result { - match value { - "refresh_token" => Ok(Field::RefreshToken), - "expires" => Ok(Field::Expires), - _ => Err(de::Error::custom("expected refresh_token or expires")), + fn visit_map(&mut self, mut visitor: V) -> Result { + let mut refresh_token = None; + let mut expires = None; + + loop { + match try!(visitor.visit_key()) { + Some(Field::RefreshToken) => refresh_token = Some(try!(visitor.visit_value())), + Some(Field::Expires) => expires = Some(try!(visitor.visit_value())), + None => break, + } + } + + let refresh_token = match refresh_token { + Some(s) => s, + None => return visitor.missing_field("refresh_token"), + }; + let expires = match expires { + Some(i) => UTC.timestamp(i, 0), + None => return visitor.missing_field("expires"), + }; + + try!(visitor.end()); + + Ok(Refresh { + refresh_token: refresh_token, + expires: expires, + }) + } + } + + enum Field { + RefreshToken, + Expires, + } + + impl Deserialize for Field { + fn deserialize(deserializer: &mut D) -> Result { + deserializer.deserialize(FieldVisitor) + } + } + + struct FieldVisitor; + impl de::Visitor for FieldVisitor { + type Value = Field; + + fn visit_str(&mut self, value: &str) -> Result { + match value { + "refresh_token" => Ok(Field::RefreshToken), + "expires" => Ok(Field::Expires), + _ => Err(de::Error::custom("expected refresh_token or expires")), + } } } } @@ -182,7 +189,6 @@ impl de::Visitor for FieldVisitor { mod tests { use chrono::{UTC, Duration, Timelike}; use rustc_serialize::json::{self, Json}; - use serde_json; use client::response::FromResponse; use super::Refresh; @@ -220,8 +226,11 @@ mod tests { assert_eq!(refresh, decoded); } + #[cfg(feature = "serde")] #[test] fn serialize_deserialize() { + use serde_json; + let original = Refresh { refresh_token: String::from("foo"), expires: UTC::now().with_nanosecond(0).unwrap(), diff --git a/src/token/statik.rs b/src/token/statik.rs index 7718716..7c6f162 100644 --- a/src/token/statik.rs +++ b/src/token/statik.rs @@ -1,6 +1,4 @@ use rustc_serialize::json::Json; -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use serde::de::impls::UnitVisitor; use super::Lifetime; use client::response::{FromResponse, ParseError, JsonHelper}; @@ -23,23 +21,30 @@ impl FromResponse for Static { } } -impl Serialize for Static { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { - serializer.serialize_unit_struct("Static") - } -} +#[cfg(feature = "serde")] +mod serde { + use serde::{Serialize, Serializer, Deserialize, Deserializer}; + use serde::de::impls::UnitVisitor; -impl Deserialize for Static { - fn deserialize(deserializer: &mut D) -> Result { - deserializer.deserialize_unit_struct("Static", UnitVisitor) - .and(Ok(Static)) + use super::Static; + + impl Serialize for Static { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> { + serializer.serialize_unit_struct("Static") + } + } + + impl Deserialize for Static { + fn deserialize(deserializer: &mut D) -> Result { + deserializer.deserialize_unit_struct("Static", UnitVisitor) + .and(Ok(Static)) + } } } #[cfg(test)] mod tests { use rustc_serialize::json::Json; - use serde_json; use client::response::{FromResponse, ParseError}; use super::Static; @@ -59,8 +64,11 @@ mod tests { ); } + #[cfg(feature = "serde")] #[test] fn serialize_deserialize() { + use serde_json; + let original = Static; let serialized = serde_json::to_value(&original); let deserialized = serde_json::from_value(serialized).unwrap();