Replace rustc_serialize with serde

This commit is contained in:
Curtis McEnroe 2017-06-04 19:53:04 -04:00
parent fea3ff6086
commit 62e8d11cb6
No known key found for this signature in database
GPG Key ID: CEA2F97ADCFCD77C
12 changed files with 186 additions and 636 deletions

91
Cargo.lock generated
View File

@ -5,9 +5,9 @@ dependencies = [
"chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "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 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)", "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 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.7.15 (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 0.7.4 (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)", "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)", "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" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
name = "foreign-types" name = "foreign-types"
version = "0.2.0" version = "0.2.0"
@ -144,7 +150,7 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "0.1.1" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -270,6 +276,11 @@ name = "pkg-config"
version = "0.3.9" version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "rand" name = "rand"
version = "0.3.15" version = "0.3.15"
@ -283,11 +294,6 @@ name = "redox_syscall"
version = "0.1.18" version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.1.7" version = "0.1.7"
@ -346,17 +352,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "0.7.15" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde_json" name = "serde_derive"
version = "0.7.4" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ 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)", "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]] [[package]]
@ -409,6 +453,11 @@ name = "unicode-normalization"
version = "0.1.4" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "url" name = "url"
version = "1.4.1" 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 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 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 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 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 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" "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 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 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 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 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 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" "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 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 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 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 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 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 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 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 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 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 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 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 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4"
"checksum serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b22e8a0554f31cb0f501e027de07b253553b308124f61c57598b9678dba35c0b" "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 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 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" "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 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-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-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 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 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" "checksum version_check 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb3950bf29e36796dea723df1747619dd331881aefef75b7cf1c58fdd738afe"

View File

@ -12,20 +12,14 @@ documentation = "https://cmcenroe.me/inth-oauth2/inth_oauth2"
repository = "https://github.com/programble/inth-oauth2" repository = "https://github.com/programble/inth-oauth2"
readme = "README.md" readme = "README.md"
[features]
default = ["serde"]
[dependencies] [dependencies]
chrono = "0.3" chrono = { version = "0.3", features = ["serde"] }
hyper = "0.10" 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" url = "1.1.0"
[dependencies.serde]
version = "0.7.0"
optional = true
[dev-dependencies] [dev-dependencies]
hyper-native-tls = "0.2" hyper-native-tls = "0.2"
serde_json = "0.7.0"
yup-hyper-mock = "2.0" yup-hyper-mock = "2.0"

View File

@ -2,7 +2,7 @@ use std::error::Error;
use std::{fmt, io}; use std::{fmt, io};
use hyper; use hyper;
use rustc_serialize::json; use serde_json;
use url; use url;
use client::response::ParseError; use client::response::ParseError;
@ -18,7 +18,7 @@ pub enum ClientError {
/// Hyper error. /// Hyper error.
Hyper(hyper::Error), Hyper(hyper::Error),
/// JSON error. /// JSON error.
Json(json::ParserError), Json(serde_json::Error),
/// Response parse error. /// Response parse error.
Parse(ParseError), Parse(ParseError),
/// OAuth 2.0 error. /// OAuth 2.0 error.
@ -75,6 +75,6 @@ macro_rules! impl_from {
impl_from!(ClientError::Io, io::Error); impl_from!(ClientError::Io, io::Error);
impl_from!(ClientError::Url, url::ParseError); impl_from!(ClientError::Url, url::ParseError);
impl_from!(ClientError::Hyper, hyper::Error); 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::Parse, ParseError);
impl_from!(ClientError::OAuth2, OAuth2Error); impl_from!(ClientError::OAuth2, OAuth2Error);

View File

@ -3,7 +3,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use hyper::{self, header, mime}; use hyper::{self, header, mime};
use rustc_serialize::json::Json; use serde_json::{self, Value};
use url::Url; use url::Url;
use url::form_urlencoded::Serializer; use url::form_urlencoded::Serializer;
@ -105,7 +105,7 @@ impl<P: Provider> Client<P> {
&'a self, &'a self,
http_client: &hyper::Client, http_client: &hyper::Client,
mut body: Serializer<String> mut body: Serializer<String>
) -> Result<Json, ClientError> { ) -> Result<Value, ClientError> {
if P::credentials_in_body() { if P::credentials_in_body() {
body.append_pair("client_id", &self.client_id); body.append_pair("client_id", &self.client_id);
body.append_pair("client_secret", &self.client_secret); body.append_pair("client_secret", &self.client_secret);
@ -129,7 +129,7 @@ impl<P: Provider> Client<P> {
.body(&body); .body(&body);
let mut response = try!(request.send()); 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); let error = OAuth2Error::from_response(&json);

View File

@ -3,19 +3,19 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use rustc_serialize::json::{self, Json}; use serde_json::Value;
/// Response parsing. /// Response parsing.
pub trait FromResponse: Sized { pub trait FromResponse: Sized {
/// Parse a JSON response. /// 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. /// 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 /// Necessary for parsing refresh token responses where the absence of a new refresh token
/// implies that the previous refresh token is still valid. /// implies that the previous refresh token is still valid.
#[allow(unused_variables)] #[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) FromResponse::from_response(json)
} }
} }
@ -54,42 +54,3 @@ impl fmt::Display for ParseError {
impl Error for ParseError { impl Error for ParseError {
fn description(&self) -> &str { "response parse error" } 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"))
}
}

View File

@ -3,9 +3,9 @@
use std::error::Error; use std::error::Error;
use std::fmt; 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. /// OAuth 2.0 error codes.
/// ///
@ -87,12 +87,14 @@ impl Error for OAuth2Error {
} }
impl FromResponse for OAuth2Error { impl FromResponse for OAuth2Error {
fn from_response(json: &Json) -> Result<Self, ParseError> { fn from_response(json: &Value) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
let code = try!(obj.get_string("error")); let code = obj.get("error")
let description = obj.get_string_option("error_description"); .and_then(Value::as_str)
let uri = obj.get_string_option("error_uri"); .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 { Ok(OAuth2Error {
code: code.into(), code: code.into(),
@ -104,14 +106,12 @@ impl FromResponse for OAuth2Error {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use rustc_serialize::json::Json;
use client::response::{FromResponse, ParseError}; use client::response::{FromResponse, ParseError};
use super::{OAuth2Error, OAuth2ErrorCode}; use super::{OAuth2Error, OAuth2ErrorCode};
#[test] #[test]
fn from_response_empty() { fn from_response_empty() {
let json = Json::from_str("{}").unwrap(); let json = "{}".parse().unwrap();
assert_eq!( assert_eq!(
ParseError::ExpectedFieldType("error", "string"), ParseError::ExpectedFieldType("error", "string"),
OAuth2Error::from_response(&json).unwrap_err() OAuth2Error::from_response(&json).unwrap_err()
@ -120,7 +120,7 @@ mod tests {
#[test] #[test]
fn from_response() { fn from_response() {
let json = Json::from_str(r#"{"error":"invalid_request"}"#).unwrap(); let json = r#"{"error":"invalid_request"}"#.parse().unwrap();
assert_eq!( assert_eq!(
OAuth2Error { OAuth2Error {
code: OAuth2ErrorCode::InvalidRequest, code: OAuth2ErrorCode::InvalidRequest,
@ -133,7 +133,8 @@ mod tests {
#[test] #[test]
fn from_response_with_description() { 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(); .unwrap();
assert_eq!( assert_eq!(
OAuth2Error { OAuth2Error {
@ -147,9 +148,9 @@ mod tests {
#[test] #[test]
fn from_response_with_uri() { fn from_response_with_uri() {
let json = Json::from_str( let json = r#"{"error":"invalid_request","error_uri":"http://example.com"}"#
r#"{"error":"invalid_request","error_uri":"http://example.com"}"# .parse()
).unwrap(); .unwrap();
assert_eq!( assert_eq!(
OAuth2Error { OAuth2Error {
code: OAuth2ErrorCode::InvalidRequest, code: OAuth2ErrorCode::InvalidRequest,

View File

@ -115,37 +115,19 @@
//! //!
//! ### Persisting tokens //! ### Persisting tokens
//! //!
//! All token types implement `Encodable` / `Decodable` from `rustc_serialize` and `Serialize` / //! All token types implement `Serialize` and `Deserialize` from `serde`.
//! `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();
//! # }
//! ```
//! //!
//! ```no_run //! ```no_run
//! # extern crate inth_oauth2; //! # extern crate inth_oauth2;
//! extern crate serde_json; //! extern crate serde_json;
//! # use inth_oauth2::Client; //! # use inth_oauth2::Client;
//! # use inth_oauth2::provider::google::Installed; //! # use inth_oauth2::provider::google::Installed;
//! # #[cfg(feature = "serde")]
//! # fn main() { //! # fn main() {
//! # let http_client = Default::default(); //! # let http_client = Default::default();
//! # let client = Client::<Installed>::new(String::new(), String::new(), None); //! # let client = Client::<Installed>::new(String::new(), String::new(), None);
//! # let token = client.request_token(&http_client, "").unwrap(); //! # let token = client.request_token(&http_client, "").unwrap();
//! let json = serde_json::to_string(&token).unwrap(); //! let json = serde_json::to_string(&token).unwrap();
//! # } //! # }
//! # #[cfg(not(feature = "serde"))]
//! # fn main() { }
//! ``` //! ```
#![warn( #![warn(
@ -160,21 +142,18 @@
variant_size_differences variant_size_differences
)] )]
#[macro_use]
extern crate serde_derive;
extern crate chrono; extern crate chrono;
extern crate hyper; extern crate hyper;
extern crate rustc_serialize; extern crate serde_json;
extern crate url; extern crate url;
#[cfg(feature = "serde")]
extern crate serde;
pub use token::{Token, Lifetime};
pub use client::{Client, ClientError};
pub mod token; pub mod token;
pub mod provider; pub mod provider;
pub mod error; pub mod error;
pub mod client; pub mod client;
#[cfg(all(test, feature = "serde"))] pub use token::{Token, Lifetime};
extern crate serde_json; pub use client::{Client, ClientError};

View File

@ -1,13 +1,13 @@
use hyper::header; use hyper::header;
use rustc_serialize::json::Json; use serde_json::Value;
use super::{Token, Lifetime}; use super::{Token, Lifetime};
use client::response::{FromResponse, ParseError, JsonHelper}; use client::response::{FromResponse, ParseError};
/// The bearer token type. /// The bearer token type.
/// ///
/// See [RFC 6750](http://tools.ietf.org/html/rfc6750). /// 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> { pub struct Bearer<L: Lifetime> {
access_token: String, access_token: String,
scope: Option<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> { impl<L: Lifetime> Bearer<L> {
fn from_response_and_lifetime(json: &Json, lifetime: L) -> Result<Self, ParseError> { fn from_response_and_lifetime(json: &Value, lifetime: L) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); 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" { if token_type != "Bearer" && token_type != "bearer" {
return Err(ParseError::ExpectedFieldValue("token_type", "Bearer")); return Err(ParseError::ExpectedFieldValue("token_type", "Bearer"));
} }
let access_token = try!(obj.get_string("access_token")); let access_token = obj.get("access_token")
let scope = obj.get_string_option("scope"); .and_then(Value::as_str)
.ok_or(ParseError::ExpectedFieldType("access_token", "string"))?;
let scope = obj.get("scope").and_then(Value::as_str);
Ok(Bearer { Ok(Bearer {
access_token: access_token.into(), access_token: access_token.into(),
@ -47,123 +51,20 @@ impl<L: Lifetime> Bearer<L> {
} }
impl<L: Lifetime> FromResponse for Bearer<L> { impl<L: Lifetime> FromResponse for Bearer<L> {
fn from_response(json: &Json) -> Result<Self, ParseError> { fn from_response(json: &Value) -> Result<Self, ParseError> {
let lifetime = try!(FromResponse::from_response(json)); let lifetime = FromResponse::from_response(json)?;
Bearer::from_response_and_lifetime(json, lifetime) Bearer::from_response_and_lifetime(json, lifetime)
} }
fn from_response_inherit(json: &Json, prev: &Self) -> Result<Self, ParseError> { fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
let lifetime = try!(FromResponse::from_response_inherit(json, &prev.lifetime)); let lifetime = FromResponse::from_response_inherit(json, &prev.lifetime)?;
Bearer::from_response_and_lifetime(json, 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)] #[cfg(test)]
mod tests { mod tests {
use chrono::{UTC, Duration}; use chrono::{UTC, Duration};
use rustc_serialize::json::Json;
use client::response::{FromResponse, ParseError}; use client::response::{FromResponse, ParseError};
use token::{Static, Refresh}; use token::{Static, Refresh};
@ -171,7 +72,7 @@ mod tests {
#[test] #[test]
fn from_response_with_invalid_token_type() { 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!( assert_eq!(
ParseError::ExpectedFieldValue("token_type", "Bearer"), ParseError::ExpectedFieldValue("token_type", "Bearer"),
Bearer::<Static>::from_response(&json).unwrap_err() Bearer::<Static>::from_response(&json).unwrap_err()
@ -180,7 +81,7 @@ mod tests {
#[test] #[test]
fn from_response_capital_b() { 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!( assert_eq!(
Bearer { Bearer {
access_token: String::from("aaaaaaaa"), access_token: String::from("aaaaaaaa"),
@ -193,7 +94,7 @@ mod tests {
#[test] #[test]
fn from_response_little_b() { 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!( assert_eq!(
Bearer { Bearer {
access_token: String::from("aaaaaaaa"), access_token: String::from("aaaaaaaa"),
@ -206,9 +107,9 @@ mod tests {
#[test] #[test]
fn from_response_with_scope() { fn from_response_with_scope() {
let json = Json::from_str( let json = r#"{"token_type":"Bearer","access_token":"aaaaaaaa","scope":"foo"}"#
r#"{"token_type":"Bearer","access_token":"aaaaaaaa","scope":"foo"}"# .parse()
).unwrap(); .unwrap();
assert_eq!( assert_eq!(
Bearer { Bearer {
access_token: String::from("aaaaaaaa"), access_token: String::from("aaaaaaaa"),
@ -221,14 +122,14 @@ mod tests {
#[test] #[test]
fn from_response_refresh() { fn from_response_refresh() {
let json = Json::from_str(r#" let json = r#"
{ {
"token_type":"Bearer", "token_type":"Bearer",
"access_token":"aaaaaaaa", "access_token":"aaaaaaaa",
"expires_in":3600, "expires_in":3600,
"refresh_token":"bbbbbbbb" "refresh_token":"bbbbbbbb"
} }
"#).unwrap(); "#.parse().unwrap();
let bearer = Bearer::<Refresh>::from_response(&json).unwrap(); let bearer = Bearer::<Refresh>::from_response(&json).unwrap();
assert_eq!("aaaaaaaa", bearer.access_token); assert_eq!("aaaaaaaa", bearer.access_token);
assert_eq!(None, bearer.scope); assert_eq!(None, bearer.scope);
@ -240,23 +141,23 @@ mod tests {
#[test] #[test]
fn from_response_inherit_refresh() { fn from_response_inherit_refresh() {
let json = Json::from_str(r#" let json = r#"
{ {
"token_type":"Bearer", "token_type":"Bearer",
"access_token":"aaaaaaaa", "access_token":"aaaaaaaa",
"expires_in":3600, "expires_in":3600,
"refresh_token":"bbbbbbbb" "refresh_token":"bbbbbbbb"
} }
"#).unwrap(); "#.parse().unwrap();
let prev = Bearer::<Refresh>::from_response(&json).unwrap(); let prev = Bearer::<Refresh>::from_response(&json).unwrap();
let json = Json::from_str(r#" let json = r#"
{ {
"token_type":"Bearer", "token_type":"Bearer",
"access_token":"cccccccc", "access_token":"cccccccc",
"expires_in":3600 "expires_in":3600
} }
"#).unwrap(); "#.parse().unwrap();
let bearer = Bearer::<Refresh>::from_response_inherit(&json, &prev).unwrap(); let bearer = Bearer::<Refresh>::from_response_inherit(&json, &prev).unwrap();
assert_eq!("cccccccc", bearer.access_token); assert_eq!("cccccccc", bearer.access_token);
assert_eq!(None, bearer.scope); assert_eq!(None, bearer.scope);
@ -265,19 +166,4 @@ mod tests {
assert!(refresh.expires() > &UTC::now()); assert!(refresh.expires() > &UTC::now());
assert!(refresh.expires() <= &(UTC::now() + Duration::seconds(3600))); 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);
}
} }

View File

@ -1,12 +1,11 @@
use chrono::{DateTime, UTC, Duration, TimeZone}; use chrono::{DateTime, UTC, Duration};
use rustc_serialize::json::Json; use serde_json::Value;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use super::Lifetime; use super::Lifetime;
use client::response::{FromResponse, ParseError, JsonHelper}; use client::response::{FromResponse, ParseError};
/// An expiring token. /// An expiring token.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Expiring { pub struct Expiring {
expires: DateTime<UTC>, expires: DateTime<UTC>,
} }
@ -21,14 +20,16 @@ impl Lifetime for Expiring {
} }
impl FromResponse for Expiring { impl FromResponse for Expiring {
fn from_response(json: &Json) -> Result<Self, ParseError> { fn from_response(json: &Value) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); 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")); 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 { Ok(Expiring {
expires: UTC::now() + Duration::seconds(expires_in), 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)] #[cfg(test)]
mod tests { mod tests {
use chrono::{UTC, Duration, Timelike}; use chrono::{UTC, Duration};
use rustc_serialize::json::{self, Json};
use client::response::FromResponse; use client::response::FromResponse;
use super::Expiring; use super::Expiring;
#[test] #[test]
fn from_response() { 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(); let expiring = Expiring::from_response(&json).unwrap();
assert!(expiring.expires > UTC::now()); assert!(expiring.expires > UTC::now());
assert!(expiring.expires <= UTC::now() + Duration::seconds(3600)); 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);
}
} }

View File

@ -29,14 +29,12 @@ pub trait Lifetime: FromResponse {
fn expired(&self) -> bool; fn expired(&self) -> bool;
} }
pub use self::bearer::Bearer;
mod bearer; mod bearer;
mod expiring;
pub use self::statik::Static; mod refresh;
mod statik; mod statik;
pub use self::bearer::Bearer;
pub use self::expiring::Expiring; pub use self::expiring::Expiring;
mod expiring;
pub use self::refresh::Refresh; pub use self::refresh::Refresh;
mod refresh; pub use self::statik::Static;

View File

@ -1,12 +1,11 @@
use chrono::{DateTime, UTC, Duration, TimeZone}; use chrono::{DateTime, UTC, Duration};
use rustc_serialize::json::Json; use serde_json::Value;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use super::Lifetime; use super::Lifetime;
use client::response::{FromResponse, ParseError, JsonHelper}; use client::response::{FromResponse, ParseError};
/// An expiring token which can be refreshed. /// An expiring token which can be refreshed.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Refresh { pub struct Refresh {
refresh_token: String, refresh_token: String,
expires: DateTime<UTC>, expires: DateTime<UTC>,
@ -27,11 +26,15 @@ impl Lifetime for Refresh {
} }
impl FromResponse for Refresh { impl FromResponse for Refresh {
fn from_response(json: &Json) -> Result<Self, ParseError> { fn from_response(json: &Value) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
let refresh_token = try!(obj.get_string("refresh_token")); let refresh_token = obj.get("refresh_token")
let expires_in = try!(obj.get_i64("expires_in")); .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 { Ok(Refresh {
refresh_token: refresh_token.into(), refresh_token: refresh_token.into(),
@ -39,14 +42,17 @@ impl FromResponse for Refresh {
}) })
} }
fn from_response_inherit(json: &Json, prev: &Self) -> Result<Self, ParseError> { fn from_response_inherit(json: &Value, prev: &Self) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
let refresh_token = try! { let refresh_token = obj.get("refresh_token")
obj.get_string("refresh_token") .and_then(Value::as_str)
.or(Ok(&prev.refresh_token)) .or(Some(&prev.refresh_token))
}; .ok_or(ParseError::ExpectedFieldType("refresh_token", "string"))?;
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(Refresh { Ok(Refresh {
refresh_token: refresh_token.into(), 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)] #[cfg(test)]
mod tests { mod tests {
use chrono::{UTC, Duration, Timelike}; use chrono::{UTC, Duration};
use rustc_serialize::json::{self, Json};
use client::response::FromResponse; use client::response::FromResponse;
use super::Refresh; use super::Refresh;
#[test] #[test]
fn from_response() { 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(); let refresh = Refresh::from_response(&json).unwrap();
assert_eq!("aaaaaaaa", refresh.refresh_token); assert_eq!("aaaaaaaa", refresh.refresh_token);
assert!(refresh.expires > UTC::now()); assert!(refresh.expires > UTC::now());
@ -204,7 +79,7 @@ mod tests {
#[test] #[test]
fn from_response_inherit() { 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 { let prev = Refresh {
refresh_token: String::from("aaaaaaaa"), refresh_token: String::from("aaaaaaaa"),
expires: UTC::now(), expires: UTC::now(),
@ -214,29 +89,4 @@ mod tests {
assert!(refresh.expires > UTC::now()); assert!(refresh.expires > UTC::now());
assert!(refresh.expires <= UTC::now() + Duration::seconds(3600)); 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);
}
} }

View File

@ -1,10 +1,10 @@
use rustc_serialize::json::Json; use serde_json::Value;
use super::Lifetime; use super::Lifetime;
use client::response::{FromResponse, ParseError, JsonHelper}; use client::response::{FromResponse, ParseError};
/// A static, non-expiring token. /// A static, non-expiring token.
#[derive(Debug, Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Static; pub struct Static;
impl Lifetime for Static { impl Lifetime for Static {
@ -12,66 +12,32 @@ impl Lifetime for Static {
} }
impl FromResponse for Static { impl FromResponse for Static {
fn from_response(json: &Json) -> Result<Self, ParseError> { fn from_response(json: &Value) -> Result<Self, ParseError> {
let obj = try!(JsonHelper(json).as_object()); let obj = json.as_object().ok_or(ParseError::ExpectedType("object"))?;
if obj.0.contains_key("expires_in") { if obj.contains_key("expires_in") {
return Err(ParseError::UnexpectedField("expires_in")); return Err(ParseError::UnexpectedField("expires_in"));
} }
Ok(Static) 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)] #[cfg(test)]
mod tests { mod tests {
use rustc_serialize::json::Json;
use client::response::{FromResponse, ParseError}; use client::response::{FromResponse, ParseError};
use super::Static; use super::Static;
#[test] #[test]
fn from_response() { fn from_response() {
let json = Json::from_str("{}").unwrap(); let json = "{}".parse().unwrap();
assert_eq!(Static, Static::from_response(&json).unwrap()); assert_eq!(Static, Static::from_response(&json).unwrap());
} }
#[test] #[test]
fn from_response_with_expires_in() { 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!( assert_eq!(
ParseError::UnexpectedField("expires_in"), ParseError::UnexpectedField("expires_in"),
Static::from_response(&json).unwrap_err() 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);
}
} }