Replace rustc_serialize with serde
This commit is contained in:
parent
fea3ff6086
commit
62e8d11cb6
|
@ -5,9 +5,9 @@ dependencies = [
|
|||
"chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper-native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"yup-hyper-mock 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -50,6 +50,7 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -79,6 +80,11 @@ dependencies = [
|
|||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.2.0"
|
||||
|
@ -144,7 +150,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.1.1"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -270,6 +276,11 @@ name = "pkg-config"
|
|||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.15"
|
||||
|
@ -283,11 +294,6 @@ name = "redox_syscall"
|
|||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.7"
|
||||
|
@ -346,17 +352,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.7.15"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "0.7.4"
|
||||
name = "serde_derive"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -409,6 +453,11 @@ name = "unicode-normalization"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.4.1"
|
||||
|
@ -461,6 +510,7 @@ dependencies = [
|
|||
"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"
|
||||
"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
|
||||
"checksum crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec"
|
||||
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
|
||||
"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
|
||||
"checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6"
|
||||
"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
|
||||
|
@ -468,7 +518,7 @@ dependencies = [
|
|||
"checksum hyper 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cb7031283266d12f2d4bf30b624bc2b2fd21bbcc00863c9928e87dc5e1699d2e"
|
||||
"checksum hyper-native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48fecce9e67dff46707980abb41f10eaa49cf0eded8dd0c26ae94b3ae5c3f705"
|
||||
"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37"
|
||||
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
|
||||
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
|
||||
|
@ -485,17 +535,21 @@ dependencies = [
|
|||
"checksum openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b34cd77cf91301fff3123fbd46b065c3b728b17a392835de34c397315dce5586"
|
||||
"checksum openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e035022a50faa380bd7ccdbd184d946ce539ebdb0a358780de92a995882af97a"
|
||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
|
||||
"checksum redox_syscall 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "3041aeb6000db123d2c9c751433f526e1f404b23213bd733167ab770c3989b4d"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
"checksum schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e45ac5e9e4698c1c138d2972bedcd90b81fe1efeba805449d2bdd54512de5f9"
|
||||
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
|
||||
"checksum security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "42ddf098d78d0b64564b23ee6345d07573e7d10e52ad86875d89ddf5f8378a02"
|
||||
"checksum security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5bacdada57ea62022500c457c8571c17dfb5e6240b7c8eac5916ffa8c7138a55"
|
||||
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||
"checksum serde 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0e0732aa8ec4267f61815a396a942ba3525062e3bd5520aa8419927cfc0a92"
|
||||
"checksum serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b22e8a0554f31cb0f501e027de07b253553b308124f61c57598b9678dba35c0b"
|
||||
"checksum serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4"
|
||||
"checksum serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "10552fad5500771f3902d0c5ba187c5881942b811b7ba0d8fbbfbf84d80806d3"
|
||||
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
|
||||
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||
"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3"
|
||||
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
|
@ -503,6 +557,7 @@ dependencies = [
|
|||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
|
||||
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum url 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2ba3456fbe5c0098cb877cf08b92b76c3e18e0be9e47c35b487220d377d24e"
|
||||
"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
|
||||
"checksum version_check 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb3950bf29e36796dea723df1747619dd331881aefef75b7cf1c58fdd738afe"
|
||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -12,20 +12,14 @@ documentation = "https://cmcenroe.me/inth-oauth2/inth_oauth2"
|
|||
repository = "https://github.com/programble/inth-oauth2"
|
||||
readme = "README.md"
|
||||
|
||||
[features]
|
||||
default = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.3"
|
||||
chrono = { version = "0.3", features = ["serde"] }
|
||||
hyper = "0.10"
|
||||
rustc-serialize = "0.3.16"
|
||||
serde = "1.0.8"
|
||||
serde_derive = "1.0.5"
|
||||
serde_json = "1.0.2"
|
||||
url = "1.1.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "0.7.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
hyper-native-tls = "0.2"
|
||||
serde_json = "0.7.0"
|
||||
yup-hyper-mock = "2.0"
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::error::Error;
|
|||
use std::{fmt, io};
|
||||
|
||||
use hyper;
|
||||
use rustc_serialize::json;
|
||||
use serde_json;
|
||||
use url;
|
||||
|
||||
use client::response::ParseError;
|
||||
|
@ -18,7 +18,7 @@ pub enum ClientError {
|
|||
/// Hyper error.
|
||||
Hyper(hyper::Error),
|
||||
/// JSON error.
|
||||
Json(json::ParserError),
|
||||
Json(serde_json::Error),
|
||||
/// Response parse error.
|
||||
Parse(ParseError),
|
||||
/// OAuth 2.0 error.
|
||||
|
@ -75,6 +75,6 @@ macro_rules! impl_from {
|
|||
impl_from!(ClientError::Io, io::Error);
|
||||
impl_from!(ClientError::Url, url::ParseError);
|
||||
impl_from!(ClientError::Hyper, hyper::Error);
|
||||
impl_from!(ClientError::Json, json::ParserError);
|
||||
impl_from!(ClientError::Json, serde_json::Error);
|
||||
impl_from!(ClientError::Parse, ParseError);
|
||||
impl_from!(ClientError::OAuth2, OAuth2Error);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use hyper::{self, header, mime};
|
||||
use rustc_serialize::json::Json;
|
||||
use serde_json::{self, Value};
|
||||
use url::Url;
|
||||
use url::form_urlencoded::Serializer;
|
||||
|
||||
|
@ -105,7 +105,7 @@ impl<P: Provider> Client<P> {
|
|||
&'a self,
|
||||
http_client: &hyper::Client,
|
||||
mut body: Serializer<String>
|
||||
) -> Result<Json, ClientError> {
|
||||
) -> Result<Value, ClientError> {
|
||||
if P::credentials_in_body() {
|
||||
body.append_pair("client_id", &self.client_id);
|
||||
body.append_pair("client_secret", &self.client_secret);
|
||||
|
@ -129,7 +129,7 @@ impl<P: Provider> Client<P> {
|
|||
.body(&body);
|
||||
|
||||
let mut response = try!(request.send());
|
||||
let json = try!(Json::from_reader(&mut response));
|
||||
let json = serde_json::from_reader(&mut response)?;
|
||||
|
||||
let error = OAuth2Error::from_response(&json);
|
||||
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use rustc_serialize::json::{self, Json};
|
||||
use serde_json::Value;
|
||||
|
||||
/// Response parsing.
|
||||
pub trait FromResponse: Sized {
|
||||
/// Parse a JSON response.
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError>;
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError>;
|
||||
|
||||
/// Parse a JSON response, inheriting missing values from the previous instance.
|
||||
///
|
||||
/// Necessary for parsing refresh token responses where the absence of a new refresh token
|
||||
/// implies that the previous refresh token is still valid.
|
||||
#[allow(unused_variables)]
|
||||
fn from_response_inherit(json: &Json, prev: &Self) -> Result<Self, ParseError> {
|
||||
fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
|
||||
FromResponse::from_response(json)
|
||||
}
|
||||
}
|
||||
|
@ -54,42 +54,3 @@ impl fmt::Display for ParseError {
|
|||
impl Error for ParseError {
|
||||
fn description(&self) -> &str { "response parse error" }
|
||||
}
|
||||
|
||||
/// JSON helper for response parsing.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct JsonHelper<'a>(pub &'a Json);
|
||||
|
||||
impl<'a> JsonHelper<'a> {
|
||||
/// Returns self as a `JsonObjectHelper` or fails with `ParseError::ExpectedType`.
|
||||
pub fn as_object(&self) -> Result<JsonObjectHelper<'a>, ParseError>{
|
||||
self.0.as_object()
|
||||
.ok_or_else(|| ParseError::ExpectedType("object"))
|
||||
.map(|o| JsonObjectHelper(o))
|
||||
}
|
||||
}
|
||||
|
||||
/// JSON object helper for response parsing.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct JsonObjectHelper<'a>(pub &'a json::Object);
|
||||
|
||||
impl<'a> JsonObjectHelper<'a> {
|
||||
/// Gets a field as a string or returns `None`.
|
||||
pub fn get_string_option(&self, key: &'static str) -> Option<&'a str> {
|
||||
self.0.get(key).and_then(Json::as_string)
|
||||
}
|
||||
|
||||
/// Gets a field as a string or fails with `ParseError::ExpectedFieldType`.
|
||||
pub fn get_string(&self, key: &'static str) -> Result<&'a str, ParseError> {
|
||||
self.get_string_option(key).ok_or_else(|| ParseError::ExpectedFieldType(key, "string"))
|
||||
}
|
||||
|
||||
/// Gets a field as an i64 or returns `None`.
|
||||
pub fn get_i64_option(&self, key: &'static str) -> Option<i64> {
|
||||
self.0.get(key).and_then(Json::as_i64)
|
||||
}
|
||||
|
||||
/// Gets a field as an i64 or fails with `ParseError::ExpectedFieldType`.
|
||||
pub fn get_i64(&self, key: &'static str) -> Result<i64, ParseError> {
|
||||
self.get_i64_option(key).ok_or_else(|| ParseError::ExpectedFieldType(key, "i64"))
|
||||
}
|
||||
}
|
||||
|
|
31
src/error.rs
31
src/error.rs
|
@ -3,9 +3,9 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use rustc_serialize::json::Json;
|
||||
use serde_json::Value;
|
||||
|
||||
use client::response::{FromResponse, ParseError, JsonHelper};
|
||||
use client::response::{FromResponse, ParseError};
|
||||
|
||||
/// OAuth 2.0 error codes.
|
||||
///
|
||||
|
@ -87,12 +87,14 @@ impl Error for OAuth2Error {
|
|||
}
|
||||
|
||||
impl FromResponse for OAuth2Error {
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
|
||||
let code = try!(obj.get_string("error"));
|
||||
let description = obj.get_string_option("error_description");
|
||||
let uri = obj.get_string_option("error_uri");
|
||||
let code = obj.get("error")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or(ParseError::ExpectedFieldType("error", "string"))?;
|
||||
let description = obj.get("error_description").and_then(Value::as_str);
|
||||
let uri = obj.get("error_uri").and_then(Value::as_str);
|
||||
|
||||
Ok(OAuth2Error {
|
||||
code: code.into(),
|
||||
|
@ -104,14 +106,12 @@ impl FromResponse for OAuth2Error {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustc_serialize::json::Json;
|
||||
|
||||
use client::response::{FromResponse, ParseError};
|
||||
use super::{OAuth2Error, OAuth2ErrorCode};
|
||||
|
||||
#[test]
|
||||
fn from_response_empty() {
|
||||
let json = Json::from_str("{}").unwrap();
|
||||
let json = "{}".parse().unwrap();
|
||||
assert_eq!(
|
||||
ParseError::ExpectedFieldType("error", "string"),
|
||||
OAuth2Error::from_response(&json).unwrap_err()
|
||||
|
@ -120,7 +120,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response() {
|
||||
let json = Json::from_str(r#"{"error":"invalid_request"}"#).unwrap();
|
||||
let json = r#"{"error":"invalid_request"}"#.parse().unwrap();
|
||||
assert_eq!(
|
||||
OAuth2Error {
|
||||
code: OAuth2ErrorCode::InvalidRequest,
|
||||
|
@ -133,7 +133,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_with_description() {
|
||||
let json = Json::from_str(r#"{"error":"invalid_request","error_description":"foo"}"#)
|
||||
let json = r#"{"error":"invalid_request","error_description":"foo"}"#
|
||||
.parse()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
OAuth2Error {
|
||||
|
@ -147,9 +148,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_with_uri() {
|
||||
let json = Json::from_str(
|
||||
r#"{"error":"invalid_request","error_uri":"http://example.com"}"#
|
||||
).unwrap();
|
||||
let json = r#"{"error":"invalid_request","error_uri":"http://example.com"}"#
|
||||
.parse()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
OAuth2Error {
|
||||
code: OAuth2ErrorCode::InvalidRequest,
|
||||
|
|
35
src/lib.rs
35
src/lib.rs
|
@ -115,37 +115,19 @@
|
|||
//!
|
||||
//! ### Persisting tokens
|
||||
//!
|
||||
//! All token types implement `Encodable` / `Decodable` from `rustc_serialize` and `Serialize` /
|
||||
//! `Deserialize` from `serde` (with the default `serde` feature).
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # extern crate inth_oauth2;
|
||||
//! # extern crate rustc_serialize;
|
||||
//! # use inth_oauth2::Client;
|
||||
//! # use inth_oauth2::provider::google::Installed;
|
||||
//! use rustc_serialize::json;
|
||||
//! # fn main() {
|
||||
//! # let http_client = Default::default();
|
||||
//! # let client = Client::<Installed>::new(String::new(), String::new(), None);
|
||||
//! # let token = client.request_token(&http_client, "").unwrap();
|
||||
//! let json = json::encode(&token).unwrap();
|
||||
//! # }
|
||||
//! ```
|
||||
//! All token types implement `Serialize` and `Deserialize` from `serde`.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # extern crate inth_oauth2;
|
||||
//! 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::<Installed>::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(
|
||||
|
@ -160,21 +142,18 @@
|
|||
variant_size_differences
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate chrono;
|
||||
extern crate hyper;
|
||||
extern crate rustc_serialize;
|
||||
extern crate serde_json;
|
||||
extern crate url;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
pub use token::{Token, Lifetime};
|
||||
pub use client::{Client, ClientError};
|
||||
|
||||
pub mod token;
|
||||
pub mod provider;
|
||||
pub mod error;
|
||||
pub mod client;
|
||||
|
||||
#[cfg(all(test, feature = "serde"))]
|
||||
extern crate serde_json;
|
||||
pub use token::{Token, Lifetime};
|
||||
pub use client::{Client, ClientError};
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use hyper::header;
|
||||
use rustc_serialize::json::Json;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::{Token, Lifetime};
|
||||
use client::response::{FromResponse, ParseError, JsonHelper};
|
||||
use client::response::{FromResponse, ParseError};
|
||||
|
||||
/// The bearer token type.
|
||||
///
|
||||
/// See [RFC 6750](http://tools.ietf.org/html/rfc6750).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Bearer<L: Lifetime> {
|
||||
access_token: String,
|
||||
scope: Option<String>,
|
||||
|
@ -27,16 +27,20 @@ impl<'a, L: Lifetime> Into<header::Authorization<header::Bearer>> for &'a Bearer
|
|||
}
|
||||
|
||||
impl<L: Lifetime> Bearer<L> {
|
||||
fn from_response_and_lifetime(json: &Json, lifetime: L) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
fn from_response_and_lifetime(json: &Value, lifetime: L) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
|
||||
let token_type = try!(obj.get_string("token_type"));
|
||||
let token_type = obj.get("token_type")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or(ParseError::ExpectedFieldType("token_type", "string"))?;
|
||||
if token_type != "Bearer" && token_type != "bearer" {
|
||||
return Err(ParseError::ExpectedFieldValue("token_type", "Bearer"));
|
||||
}
|
||||
|
||||
let access_token = try!(obj.get_string("access_token"));
|
||||
let scope = obj.get_string_option("scope");
|
||||
let access_token = obj.get("access_token")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or(ParseError::ExpectedFieldType("access_token", "string"))?;
|
||||
let scope = obj.get("scope").and_then(Value::as_str);
|
||||
|
||||
Ok(Bearer {
|
||||
access_token: access_token.into(),
|
||||
|
@ -47,123 +51,20 @@ impl<L: Lifetime> Bearer<L> {
|
|||
}
|
||||
|
||||
impl<L: Lifetime> FromResponse for Bearer<L> {
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError> {
|
||||
let lifetime = try!(FromResponse::from_response(json));
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError> {
|
||||
let lifetime = FromResponse::from_response(json)?;
|
||||
Bearer::from_response_and_lifetime(json, lifetime)
|
||||
}
|
||||
|
||||
fn from_response_inherit(json: &Json, prev: &Self) -> Result<Self, ParseError> {
|
||||
let lifetime = try!(FromResponse::from_response_inherit(json, &prev.lifetime));
|
||||
fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
|
||||
let lifetime = FromResponse::from_response_inherit(json, &prev.lifetime)?;
|
||||
Bearer::from_response_and_lifetime(json, lifetime)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use serde::{ser, de};
|
||||
|
||||
use token::Lifetime;
|
||||
use super::Bearer;
|
||||
|
||||
impl<L: Lifetime + Serialize> Serialize for Bearer<L> {
|
||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
||||
serializer.serialize_struct("Bearer", SerVisitor(self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerVisitor<'a, L: Lifetime + Serialize + 'a>(&'a Bearer<L>, u8);
|
||||
impl<'a, L: Lifetime + Serialize + 'a> ser::MapVisitor for SerVisitor<'a, L> {
|
||||
fn visit<S: Serializer>(&mut self, serializer: &mut S) -> Result<Option<()>, 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),
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> { Some(3) }
|
||||
}
|
||||
|
||||
impl<L: Lifetime + Deserialize> Deserialize for Bearer<L> {
|
||||
fn deserialize<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
static FIELDS: &'static [&'static str] = &["access_token", "scope", "lifetime"];
|
||||
deserializer.deserialize_struct("Bearer", FIELDS, DeVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
struct DeVisitor<L: Lifetime + Deserialize>(PhantomData<L>);
|
||||
impl<L: Lifetime + Deserialize> de::Visitor for DeVisitor<L> {
|
||||
type Value = Bearer<L>;
|
||||
|
||||
fn visit_map<V: de::MapVisitor>(&mut self, mut visitor: V) -> Result<Bearer<L>, 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<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldVisitor;
|
||||
impl de::Visitor for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn visit_str<E: de::Error>(&mut self, value: &str) -> Result<Field, E> {
|
||||
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")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::{UTC, Duration};
|
||||
use rustc_serialize::json::Json;
|
||||
|
||||
use client::response::{FromResponse, ParseError};
|
||||
use token::{Static, Refresh};
|
||||
|
@ -171,7 +72,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_with_invalid_token_type() {
|
||||
let json = Json::from_str(r#"{"token_type":"MAC","access_token":"aaaaaaaa"}"#).unwrap();
|
||||
let json = r#"{"token_type":"MAC","access_token":"aaaaaaaa"}"#.parse().unwrap();
|
||||
assert_eq!(
|
||||
ParseError::ExpectedFieldValue("token_type", "Bearer"),
|
||||
Bearer::<Static>::from_response(&json).unwrap_err()
|
||||
|
@ -180,7 +81,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_capital_b() {
|
||||
let json = Json::from_str(r#"{"token_type":"Bearer","access_token":"aaaaaaaa"}"#).unwrap();
|
||||
let json = r#"{"token_type":"Bearer","access_token":"aaaaaaaa"}"#.parse().unwrap();
|
||||
assert_eq!(
|
||||
Bearer {
|
||||
access_token: String::from("aaaaaaaa"),
|
||||
|
@ -193,7 +94,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_little_b() {
|
||||
let json = Json::from_str(r#"{"token_type":"bearer","access_token":"aaaaaaaa"}"#).unwrap();
|
||||
let json = r#"{"token_type":"bearer","access_token":"aaaaaaaa"}"#.parse().unwrap();
|
||||
assert_eq!(
|
||||
Bearer {
|
||||
access_token: String::from("aaaaaaaa"),
|
||||
|
@ -206,9 +107,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_with_scope() {
|
||||
let json = Json::from_str(
|
||||
r#"{"token_type":"Bearer","access_token":"aaaaaaaa","scope":"foo"}"#
|
||||
).unwrap();
|
||||
let json = r#"{"token_type":"Bearer","access_token":"aaaaaaaa","scope":"foo"}"#
|
||||
.parse()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
Bearer {
|
||||
access_token: String::from("aaaaaaaa"),
|
||||
|
@ -221,14 +122,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_refresh() {
|
||||
let json = Json::from_str(r#"
|
||||
let json = r#"
|
||||
{
|
||||
"token_type":"Bearer",
|
||||
"access_token":"aaaaaaaa",
|
||||
"expires_in":3600,
|
||||
"refresh_token":"bbbbbbbb"
|
||||
}
|
||||
"#).unwrap();
|
||||
"#.parse().unwrap();
|
||||
let bearer = Bearer::<Refresh>::from_response(&json).unwrap();
|
||||
assert_eq!("aaaaaaaa", bearer.access_token);
|
||||
assert_eq!(None, bearer.scope);
|
||||
|
@ -240,23 +141,23 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_inherit_refresh() {
|
||||
let json = Json::from_str(r#"
|
||||
let json = r#"
|
||||
{
|
||||
"token_type":"Bearer",
|
||||
"access_token":"aaaaaaaa",
|
||||
"expires_in":3600,
|
||||
"refresh_token":"bbbbbbbb"
|
||||
}
|
||||
"#).unwrap();
|
||||
"#.parse().unwrap();
|
||||
let prev = Bearer::<Refresh>::from_response(&json).unwrap();
|
||||
|
||||
let json = Json::from_str(r#"
|
||||
let json = r#"
|
||||
{
|
||||
"token_type":"Bearer",
|
||||
"access_token":"cccccccc",
|
||||
"expires_in":3600
|
||||
}
|
||||
"#).unwrap();
|
||||
"#.parse().unwrap();
|
||||
let bearer = Bearer::<Refresh>::from_response_inherit(&json, &prev).unwrap();
|
||||
assert_eq!("cccccccc", bearer.access_token);
|
||||
assert_eq!(None, bearer.scope);
|
||||
|
@ -265,19 +166,4 @@ mod tests {
|
|||
assert!(refresh.expires() > &UTC::now());
|
||||
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")),
|
||||
lifetime: Static,
|
||||
};
|
||||
let serialized = serde_json::to_value(&original);
|
||||
let deserialized = serde_json::from_value(serialized).unwrap();
|
||||
assert_eq!(original, deserialized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use chrono::{DateTime, UTC, Duration, TimeZone};
|
||||
use rustc_serialize::json::Json;
|
||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
use chrono::{DateTime, UTC, Duration};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::Lifetime;
|
||||
use client::response::{FromResponse, ParseError, JsonHelper};
|
||||
use client::response::{FromResponse, ParseError};
|
||||
|
||||
/// An expiring token.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Expiring {
|
||||
expires: DateTime<UTC>,
|
||||
}
|
||||
|
@ -21,14 +20,16 @@ impl Lifetime for Expiring {
|
|||
}
|
||||
|
||||
impl FromResponse for Expiring {
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
|
||||
if obj.0.contains_key("refresh_token") {
|
||||
if obj.contains_key("refresh_token") {
|
||||
return Err(ParseError::UnexpectedField("refresh_token"));
|
||||
}
|
||||
|
||||
let expires_in = try!(obj.get_i64("expires_in"));
|
||||
let expires_in = obj.get("expires_in")
|
||||
.and_then(Value::as_i64)
|
||||
.ok_or(ParseError::ExpectedFieldType("expires_in", "i64"))?;
|
||||
|
||||
Ok(Expiring {
|
||||
expires: UTC::now() + Duration::seconds(expires_in),
|
||||
|
@ -36,159 +37,18 @@ impl FromResponse for Expiring {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
struct Serializable {
|
||||
expires: i64,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Expiring> for Serializable {
|
||||
fn from(expiring: &Expiring) -> Self {
|
||||
Serializable {
|
||||
expires: expiring.expires.timestamp(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Expiring> for Serializable {
|
||||
fn into(self) -> Expiring {
|
||||
Expiring {
|
||||
expires: UTC.timestamp(self.expires, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Expiring {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
Serializable::from(self).encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Expiring {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||
Serializable::decode(d).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use chrono::{UTC, TimeZone};
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use serde::{ser, de};
|
||||
|
||||
use super::Expiring;
|
||||
|
||||
impl Serialize for Expiring {
|
||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
||||
serializer.serialize_struct("Expiring", SerVisitor(self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerVisitor<'a>(&'a Expiring, u8);
|
||||
impl<'a> ser::MapVisitor for SerVisitor<'a> {
|
||||
fn visit<S: Serializer>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error> {
|
||||
self.1 += 1;
|
||||
match self.1 {
|
||||
1 => serializer.serialize_struct_elt("expires", &self.0.expires.timestamp()).map(Some),
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> { Some(1) }
|
||||
}
|
||||
|
||||
impl Deserialize for Expiring {
|
||||
fn deserialize<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
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<V: de::MapVisitor>(&mut self, mut visitor: V) -> Result<Expiring, V::Error> {
|
||||
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<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldVisitor;
|
||||
impl de::Visitor for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn visit_str<E: de::Error>(&mut self, value: &str) -> Result<Field, E> {
|
||||
match value {
|
||||
"expires" => Ok(Field::Expires),
|
||||
_ => Err(de::Error::custom("expected expires")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::{UTC, Duration, Timelike};
|
||||
use rustc_serialize::json::{self, Json};
|
||||
use chrono::{UTC, Duration};
|
||||
|
||||
use client::response::FromResponse;
|
||||
use super::Expiring;
|
||||
|
||||
#[test]
|
||||
fn from_response() {
|
||||
let json = Json::from_str(r#"{"expires_in":3600}"#).unwrap();
|
||||
let json = r#"{"expires_in":3600}"#.parse().unwrap();
|
||||
let expiring = Expiring::from_response(&json).unwrap();
|
||||
assert!(expiring.expires > UTC::now());
|
||||
assert!(expiring.expires <= UTC::now() + Duration::seconds(3600));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_decode() {
|
||||
let expiring = Expiring {
|
||||
expires: UTC::now().with_nanosecond(0).unwrap(),
|
||||
};
|
||||
let json = json::encode(&expiring).unwrap();
|
||||
let decoded = json::decode(&json).unwrap();
|
||||
assert_eq!(expiring, decoded);
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn serialize_deserialize() {
|
||||
use serde_json;
|
||||
|
||||
let original = Expiring {
|
||||
expires: UTC::now().with_nanosecond(0).unwrap(),
|
||||
};
|
||||
let serialized = serde_json::to_value(&original);
|
||||
let deserialized = serde_json::from_value(serialized).unwrap();
|
||||
assert_eq!(original, deserialized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,12 @@ pub trait Lifetime: FromResponse {
|
|||
fn expired(&self) -> bool;
|
||||
}
|
||||
|
||||
pub use self::bearer::Bearer;
|
||||
mod bearer;
|
||||
|
||||
pub use self::statik::Static;
|
||||
mod expiring;
|
||||
mod refresh;
|
||||
mod statik;
|
||||
|
||||
pub use self::bearer::Bearer;
|
||||
pub use self::expiring::Expiring;
|
||||
mod expiring;
|
||||
|
||||
pub use self::refresh::Refresh;
|
||||
mod refresh;
|
||||
pub use self::statik::Static;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use chrono::{DateTime, UTC, Duration, TimeZone};
|
||||
use rustc_serialize::json::Json;
|
||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
use chrono::{DateTime, UTC, Duration};
|
||||
use serde_json::Value;
|
||||
|
||||
use super::Lifetime;
|
||||
use client::response::{FromResponse, ParseError, JsonHelper};
|
||||
use client::response::{FromResponse, ParseError};
|
||||
|
||||
/// An expiring token which can be refreshed.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Refresh {
|
||||
refresh_token: String,
|
||||
expires: DateTime<UTC>,
|
||||
|
@ -27,11 +26,15 @@ impl Lifetime for Refresh {
|
|||
}
|
||||
|
||||
impl FromResponse for Refresh {
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
|
||||
let refresh_token = try!(obj.get_string("refresh_token"));
|
||||
let expires_in = try!(obj.get_i64("expires_in"));
|
||||
let refresh_token = obj.get("refresh_token")
|
||||
.and_then(Value::as_str)
|
||||
.ok_or(ParseError::ExpectedFieldType("refresh_token", "string"))?;
|
||||
let expires_in = obj.get("expires_in")
|
||||
.and_then(Value::as_i64)
|
||||
.ok_or(ParseError::ExpectedFieldType("expires_in", "i64"))?;
|
||||
|
||||
Ok(Refresh {
|
||||
refresh_token: refresh_token.into(),
|
||||
|
@ -39,14 +42,17 @@ impl FromResponse for Refresh {
|
|||
})
|
||||
}
|
||||
|
||||
fn from_response_inherit(json: &Json, prev: &Self) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
|
||||
let refresh_token = try! {
|
||||
obj.get_string("refresh_token")
|
||||
.or(Ok(&prev.refresh_token))
|
||||
};
|
||||
let expires_in = try!(obj.get_i64("expires_in"));
|
||||
let refresh_token = obj.get("refresh_token")
|
||||
.and_then(Value::as_str)
|
||||
.or(Some(&prev.refresh_token))
|
||||
.ok_or(ParseError::ExpectedFieldType("refresh_token", "string"))?;
|
||||
|
||||
let expires_in = obj.get("expires_in")
|
||||
.and_then(Value::as_i64)
|
||||
.ok_or(ParseError::ExpectedFieldType("expires_in", "i64"))?;
|
||||
|
||||
Ok(Refresh {
|
||||
refresh_token: refresh_token.into(),
|
||||
|
@ -55,147 +61,16 @@ impl FromResponse for Refresh {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
struct Serializable {
|
||||
refresh_token: String,
|
||||
expires: i64,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Refresh> for Serializable {
|
||||
fn from(refresh: &Refresh) -> Self {
|
||||
Serializable {
|
||||
refresh_token: refresh.refresh_token.clone(),
|
||||
expires: refresh.expires.timestamp(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Refresh> for Serializable {
|
||||
fn into(self) -> Refresh {
|
||||
Refresh {
|
||||
refresh_token: self.refresh_token,
|
||||
expires: UTC.timestamp(self.expires, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Refresh {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
Serializable::from(self).encode(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Refresh {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
|
||||
Serializable::decode(d).map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use chrono::{UTC, TimeZone};
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use serde::{ser, de};
|
||||
|
||||
use super::Refresh;
|
||||
|
||||
impl Serialize for Refresh {
|
||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
||||
serializer.serialize_struct("Refresh", SerVisitor(self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerVisitor<'a>(&'a Refresh, u8);
|
||||
impl<'a> ser::MapVisitor for SerVisitor<'a> {
|
||||
fn visit<S: Serializer>(&mut self, serializer: &mut S) -> Result<Option<()>, 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),
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> Option<usize> { Some(2) }
|
||||
}
|
||||
|
||||
impl Deserialize for Refresh {
|
||||
fn deserialize<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
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<V: de::MapVisitor>(&mut self, mut visitor: V) -> Result<Refresh, V::Error> {
|
||||
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<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct FieldVisitor;
|
||||
impl de::Visitor for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn visit_str<E: de::Error>(&mut self, value: &str) -> Result<Field, E> {
|
||||
match value {
|
||||
"refresh_token" => Ok(Field::RefreshToken),
|
||||
"expires" => Ok(Field::Expires),
|
||||
_ => Err(de::Error::custom("expected refresh_token or expires")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::{UTC, Duration, Timelike};
|
||||
use rustc_serialize::json::{self, Json};
|
||||
use chrono::{UTC, Duration};
|
||||
|
||||
use client::response::FromResponse;
|
||||
use super::Refresh;
|
||||
|
||||
#[test]
|
||||
fn from_response() {
|
||||
let json = Json::from_str(r#"{"refresh_token":"aaaaaaaa","expires_in":3600}"#).unwrap();
|
||||
let json = r#"{"refresh_token":"aaaaaaaa","expires_in":3600}"#.parse().unwrap();
|
||||
let refresh = Refresh::from_response(&json).unwrap();
|
||||
assert_eq!("aaaaaaaa", refresh.refresh_token);
|
||||
assert!(refresh.expires > UTC::now());
|
||||
|
@ -204,7 +79,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn from_response_inherit() {
|
||||
let json = Json::from_str(r#"{"expires_in":3600}"#).unwrap();
|
||||
let json = r#"{"expires_in":3600}"#.parse().unwrap();
|
||||
let prev = Refresh {
|
||||
refresh_token: String::from("aaaaaaaa"),
|
||||
expires: UTC::now(),
|
||||
|
@ -214,29 +89,4 @@ mod tests {
|
|||
assert!(refresh.expires > UTC::now());
|
||||
assert!(refresh.expires <= UTC::now() + Duration::seconds(3600));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_decode() {
|
||||
let refresh = Refresh {
|
||||
refresh_token: String::from("foo"),
|
||||
expires: UTC::now().with_nanosecond(0).unwrap(),
|
||||
};
|
||||
let json = json::encode(&refresh).unwrap();
|
||||
let decoded = json::decode(&json).unwrap();
|
||||
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(),
|
||||
};
|
||||
let serialized = serde_json::to_value(&original);
|
||||
let deserialized = serde_json::from_value(serialized).unwrap();
|
||||
assert_eq!(original, deserialized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use rustc_serialize::json::Json;
|
||||
use serde_json::Value;
|
||||
|
||||
use super::Lifetime;
|
||||
use client::response::{FromResponse, ParseError, JsonHelper};
|
||||
use client::response::{FromResponse, ParseError};
|
||||
|
||||
/// A static, non-expiring token.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Static;
|
||||
|
||||
impl Lifetime for Static {
|
||||
|
@ -12,66 +12,32 @@ impl Lifetime for Static {
|
|||
}
|
||||
|
||||
impl FromResponse for Static {
|
||||
fn from_response(json: &Json) -> Result<Self, ParseError> {
|
||||
let obj = try!(JsonHelper(json).as_object());
|
||||
if obj.0.contains_key("expires_in") {
|
||||
fn from_response(json: &Value) -> Result<Self, ParseError> {
|
||||
let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
|
||||
if obj.contains_key("expires_in") {
|
||||
return Err(ParseError::UnexpectedField("expires_in"));
|
||||
}
|
||||
Ok(Static)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde {
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use serde::de::impls::UnitVisitor;
|
||||
|
||||
use super::Static;
|
||||
|
||||
impl Serialize for Static {
|
||||
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
|
||||
serializer.serialize_unit_struct("Static")
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for Static {
|
||||
fn deserialize<D: Deserializer>(deserializer: &mut D) -> Result<Self, D::Error> {
|
||||
deserializer.deserialize_unit_struct("Static", UnitVisitor)
|
||||
.and(Ok(Static))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rustc_serialize::json::Json;
|
||||
|
||||
use client::response::{FromResponse, ParseError};
|
||||
use super::Static;
|
||||
|
||||
#[test]
|
||||
fn from_response() {
|
||||
let json = Json::from_str("{}").unwrap();
|
||||
let json = "{}".parse().unwrap();
|
||||
assert_eq!(Static, Static::from_response(&json).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_response_with_expires_in() {
|
||||
let json = Json::from_str(r#"{"expires_in":3600}"#).unwrap();
|
||||
let json = r#"{"expires_in":3600}"#.parse().unwrap();
|
||||
assert_eq!(
|
||||
ParseError::UnexpectedField("expires_in"),
|
||||
Static::from_response(&json).unwrap_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[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();
|
||||
assert_eq!(original, deserialized);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue