Browse Source

Use serde for json serialization.

Paul Lietar 8 years ago
parent
commit
24471eef9b
8 changed files with 115 additions and 36 deletions
  1. 63 0
      Cargo.lock
  2. 6 1
      Cargo.toml
  3. 1 1
      README.md
  4. 3 1
      build.rs
  5. 3 3
      src/apresolve.rs
  6. 2 2
      src/authentication/facebook.rs
  7. 33 27
      src/authentication/mod.rs
  8. 4 1
      src/lib.rs

+ 63 - 0
Cargo.lock

@@ -26,6 +26,10 @@ dependencies = [
  "rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_macros 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)",
  "tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -209,6 +213,11 @@ dependencies = [
  "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "itoa"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "json_macros"
 version = "0.3.1"
@@ -530,6 +539,14 @@ dependencies = [
  "syntex_syntax 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "quasi_macros"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quasi_codegen 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "quine-mc_cluskey"
 version = "0.2.2"
@@ -609,6 +626,52 @@ dependencies = [
  "nom 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "serde"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_codegen"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aster 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi_codegen 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quasi_macros 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen_internals 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_codegen_internals"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_errors 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.37.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_macros"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde_codegen 0.7.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "shannon"
 version = "0.1.1"

+ 6 - 1
Cargo.toml

@@ -31,6 +31,9 @@ rand            = "~0.3.13"
 rpassword       = "~0.2.2"
 rust-crypto     = "~0.2.34"
 rustc-serialize = "~0.3.16"
+serde           = "0.7"
+serde_json      = "0.7"
+serde_macros    = { version = "0.7", optional = true }
 tempfile        = "~2.1.3"
 time            = "~0.1.34"
 url             = "~0.5.0"
@@ -57,10 +60,12 @@ openssl         = { version = "0.7", optional = true }
 vergen          = "~0.1.0"
 protobuf_macros = { git = "https://github.com/plietar/rust-protobuf-macros" }
 json_macros     = { git = "https://github.com/plietar/json_macros" }
+serde_codegen   = { version = "0.7", optional = true }
 
 [features]
 discovery         = ["dns-sd"]
-with-syntex       = ["protobuf_macros/with-syntex", "json_macros/with-syntex"]
+with-syntex       = ["serde_codegen", "protobuf_macros/with-syntex", "json_macros/with-syntex"]
+nightly           = ["serde_macros"]
 with-tremor       = ["tremor"]
 facebook          = ["hyper/ssl", "openssl"]
 portaudio-backend = ["portaudio"]

+ 1 - 1
README.md

@@ -81,7 +81,7 @@ The following backends are currently available :
 ## Development
 When developing *librespot*, it is preferable to use Rust nightly, and build it using the following :
 ```shell
-cargo build --no-default-features --features portaudio-backend
+cargo build --no-default-features --features "nightly portaudio-backend"
 ```
 
 This produces better compilation error messages than with the default configuration.

+ 3 - 1
build.rs

@@ -4,6 +4,7 @@ extern crate vergen;
 fn codegen() {
     extern crate json_macros;
     extern crate protobuf_macros;
+    extern crate serde_codegen;
 
     use std::env;
     use std::path::PathBuf;
@@ -11,7 +12,8 @@ fn codegen() {
     let out = PathBuf::from(env::var("OUT_DIR").unwrap());
 
     json_macros::expand("src/lib.in.rs", &out.join("lib.tmp0.rs")).unwrap();
-    protobuf_macros::expand(&out.join("lib.tmp0.rs"), &out.join("lib.rs")).unwrap();
+    serde_codegen::expand(&out.join("lib.tmp0.rs"), &out.join("lib.tmp1.rs")).unwrap();
+    protobuf_macros::expand(&out.join("lib.tmp1.rs"), &out.join("lib.rs")).unwrap();
 }
 
 #[cfg(not(feature = "with-syntex"))]

+ 3 - 3
src/apresolve.rs

@@ -2,9 +2,9 @@ const APRESOLVE_ENDPOINT : &'static str = "http://apresolve.spotify.com/";
 
 use hyper;
 use std::io::Read;
-use rustc_serialize::json;
+use serde_json;
 
-#[derive(RustcDecodable)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct APResolveData {
     ap_list: Vec<String>
 }
@@ -16,7 +16,7 @@ pub fn apresolve() -> Result<Vec<String>, ()> {
     let mut data = String::new();
     response.read_to_string(&mut data).unwrap();
 
-    let data : APResolveData = json::decode(&data).unwrap();
+    let data : APResolveData = serde_json::from_str(&data).unwrap();
 
     Ok(data.ap_list)
 }

+ 2 - 2
src/authentication/facebook.rs

@@ -5,7 +5,7 @@ use hyper::server::Response;
 use hyper::uri::RequestUri;
 use hyper::header::AccessControlAllowOrigin;
 use rand::{self, Rng};
-use rustc_serialize::json;
+use serde_json;
 use std::collections::BTreeMap;
 use std::io::Read;
 use std::sync::{mpsc, Mutex};
@@ -63,7 +63,7 @@ fn facebook_get_me_id(token: &str) -> Result<String, ()> {
     let mut body = String::new();
     response.read_to_string(&mut body).unwrap();
 
-    let mut result : BTreeMap<String, String> = json::decode(&body).unwrap();
+    let mut result : BTreeMap<String, String> = serde_json::from_str(&body).unwrap();
     Ok(result.remove("id").unwrap())
 }
 

+ 33 - 27
src/authentication/mod.rs

@@ -6,27 +6,27 @@ use crypto::hmac::Hmac;
 use crypto::pbkdf2::pbkdf2;
 use crypto::sha1::Sha1;
 use protobuf::ProtobufEnum;
+use serde;
+use serde_json;
 use std::io::{self, Read, Write};
 use std::fs::File;
 use std::path::Path;
 use rustc_serialize::base64::{self, FromBase64, ToBase64};
-use rustc_serialize::json;
 
 use protocol::authentication::AuthenticationType;
 
 #[derive(Debug, Clone)]
+#[derive(Serialize, Deserialize)]
 pub struct Credentials {
     pub username: String,
+
+    #[serde(serialize_with="serialize_protobuf_enum")]
+    #[serde(deserialize_with="deserialize_protobuf_enum")]
     pub auth_type: AuthenticationType,
-    pub auth_data: Vec<u8>,
-}
 
-#[derive(Debug, Clone)]
-#[derive(RustcDecodable, RustcEncodable)]
-struct StoredCredentials {
-    pub username: String,
-    pub auth_type: i32,
-    pub auth_data: String,
+    #[serde(serialize_with="serialize_base64")]
+    #[serde(deserialize_with="deserialize_base64")]
+    pub auth_data: Vec<u8>,
 }
 
 impl Credentials {
@@ -124,7 +124,7 @@ impl Credentials {
         let mut contents = String::new();
         reader.read_to_string(&mut contents).unwrap();
 
-        json::decode::<StoredCredentials>(&contents).unwrap().into()
+        serde_json::from_str(&contents).unwrap()
     }
 
     pub fn from_file<P: AsRef<Path>>(path: P) -> Option<Credentials> {
@@ -132,7 +132,7 @@ impl Credentials {
     }
 
     pub fn save_to_writer<W: Write>(&self, writer: &mut W) {
-        let contents = json::encode::<StoredCredentials>(&self.clone().into()).unwrap();
+        let contents = serde_json::to_string(&self.clone()).unwrap();
         writer.write_all(contents.as_bytes()).unwrap();
     }
 
@@ -142,24 +142,30 @@ impl Credentials {
     }
 }
 
-impl From<Credentials> for StoredCredentials {
-    fn from(credentials: Credentials) -> StoredCredentials {
-        StoredCredentials {
-            username: credentials.username,
-            auth_type: credentials.auth_type.value(),
-            auth_data: credentials.auth_data.to_base64(base64::STANDARD),
-        }
-    }
+fn serialize_protobuf_enum<T, S>(v: &T, ser: &mut S) -> Result<(), S::Error>
+    where T: ProtobufEnum, S: serde::Serializer {
+
+    serde::Serialize::serialize(&v.value(), ser)
 }
 
-impl From<StoredCredentials> for Credentials {
-    fn from(credentials: StoredCredentials) -> Credentials {
-        Credentials {
-            username: credentials.username,
-            auth_type: AuthenticationType::from_i32(credentials.auth_type).unwrap(),
-            auth_data: credentials.auth_data.from_base64().unwrap(),
-        }
-    }
+fn deserialize_protobuf_enum<T, D>(de: &mut D) -> Result<T, D::Error>
+    where T: ProtobufEnum, D: serde::Deserializer {
+
+    let v : i32 = try!(serde::Deserialize::deserialize(de));
+    T::from_i32(v).ok_or(serde::Error::invalid_value("Invalid enum value"))
+}
+
+fn serialize_base64<T, S>(v: &T, ser: &mut S) -> Result<(), S::Error>
+    where T: AsRef<[u8]>, S: serde::Serializer {
+
+    serde::Serialize::serialize(&v.as_ref().to_base64(base64::STANDARD), ser)
+}
+
+fn deserialize_base64<D>(de: &mut D) -> Result<Vec<u8>, D::Error>
+    where D: serde::Deserializer {
+
+    let v : String = try!(serde::Deserialize::deserialize(de));
+    v.from_base64().map_err(|e| serde::Error::custom(e.to_string()))
 }
 
 #[cfg(feature = "discovery")]

+ 4 - 1
src/lib.rs

@@ -1,8 +1,9 @@
 #![crate_name = "librespot"]
 
-#![cfg_attr(not(feature = "with-syntex"), feature(plugin))]
+#![cfg_attr(not(feature = "with-syntex"), feature(plugin, custom_derive))]
 #![cfg_attr(not(feature = "with-syntex"), plugin(protobuf_macros))]
 #![cfg_attr(not(feature = "with-syntex"), plugin(json_macros))]
+#![cfg_attr(not(feature = "with-syntex"), plugin(serde_macros))]
 
 #![cfg_attr(feature="clippy", feature(plugin))]
 #![cfg_attr(feature="clippy", plugin(clippy))]
@@ -24,6 +25,8 @@ extern crate shannon;
 extern crate rand;
 extern crate rpassword;
 extern crate rustc_serialize;
+extern crate serde;
+extern crate serde_json;
 extern crate time;
 extern crate tempfile;
 extern crate url;