From 4fb8c71b0a2ca2114f492e445a15a6bd0595dab8 Mon Sep 17 00:00:00 2001 From: Sasha Hilton Date: Sun, 25 Feb 2018 03:04:07 +0100 Subject: [PATCH 1/4] Set SpotifyId methods to return Result --- connect/src/spirc.rs | 2 +- core/src/spotify_id.rs | 13 +++++++------ examples/play.rs | 2 +- metadata/src/lib.rs | 18 +++++++++--------- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index 2b036143..f9c692cc 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -680,7 +680,7 @@ impl SpircTask { let index = self.state.get_playing_track_index(); let track = { let gid = self.state.get_track()[index as usize].get_gid(); - SpotifyId::from_raw(gid) + SpotifyId::from_raw(gid).unwrap() }; let position = self.state.get_position_ms(); diff --git a/core/src/spotify_id.rs b/core/src/spotify_id.rs index 5d99cb67..0472ca3f 100644 --- a/core/src/spotify_id.rs +++ b/core/src/spotify_id.rs @@ -1,6 +1,7 @@ use byteorder::{BigEndian, ByteOrder}; use std; use std::fmt; +use std::io::Result; use util::u128; // Unneeded since 1.21 #[allow(unused_imports)] @@ -13,7 +14,7 @@ const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDE const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef"; impl SpotifyId { - pub fn from_base16(id: &str) -> SpotifyId { + pub fn from_base16(id: &str) -> Result { assert!(id.is_ascii()); let data = id.as_bytes(); @@ -24,10 +25,10 @@ impl SpotifyId { n = n + u128::from(d); } - SpotifyId(n) + Ok(SpotifyId(n)) } - pub fn from_base62(id: &str) -> SpotifyId { + pub fn from_base62(id: &str) -> Result { assert!(id.is_ascii()); let data = id.as_bytes(); @@ -38,16 +39,16 @@ impl SpotifyId { n = n + u128::from(d); } - SpotifyId(n) + Ok(SpotifyId(n)) } - pub fn from_raw(data: &[u8]) -> SpotifyId { + pub fn from_raw(data: &[u8]) -> Result { assert_eq!(data.len(), 16); let high = BigEndian::read_u64(&data[0..8]); let low = BigEndian::read_u64(&data[8..16]); - SpotifyId(u128::from_parts(high, low)) + Ok(SpotifyId(u128::from_parts(high, low))) } pub fn to_base16(&self) -> String { diff --git a/examples/play.rs b/examples/play.rs index 4dd8601c..798cd242 100644 --- a/examples/play.rs +++ b/examples/play.rs @@ -28,7 +28,7 @@ fn main() { let password = args[2].to_owned(); let credentials = Credentials::with_password(username, password); - let track = SpotifyId::from_base62(&args[3]); + let track = SpotifyId::from_base62(&args[3]).unwrap(); let backend = audio_backend::find(None).unwrap(); diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index 0103a3b0..a18a6940 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -113,7 +113,7 @@ impl Metadata for Track { let artists = msg.get_artist() .iter() .filter(|artist| artist.has_gid()) - .map(|artist| SpotifyId::from_raw(artist.get_gid())) + .map(|artist| SpotifyId::from_raw(artist.get_gid()).unwrap()) .collect::>(); let files = msg.get_file() @@ -127,15 +127,15 @@ impl Metadata for Track { .collect(); Track { - id: SpotifyId::from_raw(msg.get_gid()), + id: SpotifyId::from_raw(msg.get_gid()).unwrap(), name: msg.get_name().to_owned(), duration: msg.get_duration(), - album: SpotifyId::from_raw(msg.get_album().get_gid()), + album: SpotifyId::from_raw(msg.get_album().get_gid()).unwrap(), artists: artists, files: files, alternatives: msg.get_alternative() .iter() - .map(|alt| SpotifyId::from_raw(alt.get_gid())) + .map(|alt| SpotifyId::from_raw(alt.get_gid()).unwrap()) .collect(), available: parse_restrictions(msg.get_restriction(), &country, "premium"), } @@ -153,14 +153,14 @@ impl Metadata for Album { let artists = msg.get_artist() .iter() .filter(|artist| artist.has_gid()) - .map(|artist| SpotifyId::from_raw(artist.get_gid())) + .map(|artist| SpotifyId::from_raw(artist.get_gid()).unwrap()) .collect::>(); let tracks = msg.get_disc() .iter() .flat_map(|disc| disc.get_track()) .filter(|track| track.has_gid()) - .map(|track| SpotifyId::from_raw(track.get_gid())) + .map(|track| SpotifyId::from_raw(track.get_gid()).unwrap()) .collect::>(); let covers = msg.get_cover_group() @@ -175,7 +175,7 @@ impl Metadata for Album { .collect::>(); Album { - id: SpotifyId::from_raw(msg.get_gid()), + id: SpotifyId::from_raw(msg.get_gid()).unwrap(), name: msg.get_name().to_owned(), artists: artists, tracks: tracks, @@ -202,13 +202,13 @@ impl Metadata for Artist { .get_track() .iter() .filter(|track| track.has_gid()) - .map(|track| SpotifyId::from_raw(track.get_gid())) + .map(|track| SpotifyId::from_raw(track.get_gid()).unwrap()) .collect::>(), None => Vec::new(), }; Artist { - id: SpotifyId::from_raw(msg.get_gid()), + id: SpotifyId::from_raw(msg.get_gid()).unwrap(), name: msg.get_name().to_owned(), top_tracks: top_tracks, } From 084646e21b4ef5ed8abb7a89a44fb03e8ea0e9c8 Mon Sep 17 00:00:00 2001 From: Sasha Hilton Date: Sun, 25 Feb 2018 05:40:00 +0100 Subject: [PATCH 2/4] Use prompt for password in main.rs --- core/src/authentication.rs | 12 +++++------- src/main.rs | 10 +++++++++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/src/authentication.rs b/core/src/authentication.rs index c079d543..2946f477 100644 --- a/core/src/authentication.rs +++ b/core/src/authentication.rs @@ -7,11 +7,11 @@ use crypto::hmac::Hmac; use crypto::pbkdf2::pbkdf2; use crypto::sha1::Sha1; use protobuf::ProtobufEnum; -use rpassword; use serde; use serde_json; use std::fs::File; -use std::io::{self, stderr, Read, Write}; +use std::io::{self, Read, Write}; +use std::ops::FnOnce; use std::path::Path; use protocol::authentication::AuthenticationType; @@ -180,10 +180,11 @@ where base64::decode(&v).map_err(|e| serde::de::Error::custom(e.to_string())) } -pub fn get_credentials( +pub fn get_credentials String>( username: Option, password: Option, cached_credentials: Option, + prompt: F, ) -> Option { match (username, password, cached_credentials) { (Some(username), Some(password), _) => Some(Credentials::with_password(username, password)), @@ -193,10 +194,7 @@ pub fn get_credentials( } (Some(username), None, _) => { - write!(stderr(), "Password for {}: ", username).unwrap(); - stderr().flush().unwrap(); - let password = rpassword::read_password().unwrap(); - Some(Credentials::with_password(username.clone(), password)) + Some(Credentials::with_password(username.clone(), prompt(&username))) } (None, _, Some(credentials)) => Some(credentials), diff --git a/src/main.rs b/src/main.rs index a42be82d..e3adc498 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate env_logger; extern crate futures; extern crate getopts; extern crate librespot; +extern crate rpassword; extern crate tokio_core; extern crate tokio_io; extern crate tokio_signal; @@ -177,10 +178,17 @@ fn setup(args: &[String]) -> Setup { let credentials = { let cached_credentials = cache.as_ref().and_then(Cache::credentials); + let password = |username: &String| -> String { + write!(stderr(), "Password for {}: ", username).unwrap(); + stderr().flush().unwrap(); + rpassword::read_password().unwrap() + }; + get_credentials( matches.opt_str("username"), matches.opt_str("password"), - cached_credentials + cached_credentials, + password ) }; From 0abad9a8f812103b1a998d25e1a7bfe261c67967 Mon Sep 17 00:00:00 2001 From: Sasha Hilton Date: Sun, 25 Feb 2018 15:47:57 +0100 Subject: [PATCH 3/4] Add custom SpotifyIdError type --- core/src/authentication.rs | 7 ++++--- core/src/spotify_id.rs | 26 +++++++++++++++++--------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/core/src/authentication.rs b/core/src/authentication.rs index 2946f477..c1fbed0d 100644 --- a/core/src/authentication.rs +++ b/core/src/authentication.rs @@ -193,9 +193,10 @@ pub fn get_credentials String>( Some(credentials.clone()) } - (Some(username), None, _) => { - Some(Credentials::with_password(username.clone(), prompt(&username))) - } + (Some(username), None, _) => Some(Credentials::with_password( + username.clone(), + prompt(&username), + )), (None, _, Some(credentials)) => Some(credentials), diff --git a/core/src/spotify_id.rs b/core/src/spotify_id.rs index 0472ca3f..2169ee6f 100644 --- a/core/src/spotify_id.rs +++ b/core/src/spotify_id.rs @@ -1,7 +1,6 @@ use byteorder::{BigEndian, ByteOrder}; use std; use std::fmt; -use std::io::Result; use util::u128; // Unneeded since 1.21 #[allow(unused_imports)] @@ -10,17 +9,22 @@ use std::ascii::AsciiExt; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct SpotifyId(u128); +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct SpotifyIdError; + const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef"; impl SpotifyId { - pub fn from_base16(id: &str) -> Result { - assert!(id.is_ascii()); + pub fn from_base16(id: &str) -> Result { let data = id.as_bytes(); let mut n: u128 = u128::zero(); for c in data { - let d = BASE16_DIGITS.iter().position(|e| e == c).unwrap() as u8; + let d = match BASE16_DIGITS.iter().position(|e| e == c) { + None => return Err(SpotifyIdError), + Some(x) => x as u8, + }; n = n * u128::from(16); n = n + u128::from(d); } @@ -28,13 +32,15 @@ impl SpotifyId { Ok(SpotifyId(n)) } - pub fn from_base62(id: &str) -> Result { - assert!(id.is_ascii()); + pub fn from_base62(id: &str) -> Result { let data = id.as_bytes(); let mut n: u128 = u128::zero(); for c in data { - let d = BASE62_DIGITS.iter().position(|e| e == c).unwrap() as u8; + let d = match BASE62_DIGITS.iter().position(|e| e == c) { + None => return Err(SpotifyIdError), + Some(x) => x as u8, + }; n = n * u128::from(62); n = n + u128::from(d); } @@ -42,8 +48,10 @@ impl SpotifyId { Ok(SpotifyId(n)) } - pub fn from_raw(data: &[u8]) -> Result { - assert_eq!(data.len(), 16); + pub fn from_raw(data: &[u8]) -> Result { + if data.len() != 16 { + return Err(SpotifyIdError) + }; let high = BigEndian::read_u64(&data[0..8]); let low = BigEndian::read_u64(&data[8..16]); From 197d80edbfc89ef7d72be20b90920b2fbb39961c Mon Sep 17 00:00:00 2001 From: Sasha Hilton Date: Sun, 25 Feb 2018 16:33:32 +0100 Subject: [PATCH 4/4] Fix formatting --- core/src/spotify_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/spotify_id.rs b/core/src/spotify_id.rs index 2169ee6f..314708e8 100644 --- a/core/src/spotify_id.rs +++ b/core/src/spotify_id.rs @@ -50,7 +50,7 @@ impl SpotifyId { pub fn from_raw(data: &[u8]) -> Result { if data.len() != 16 { - return Err(SpotifyIdError) + return Err(SpotifyIdError); }; let high = BigEndian::read_u64(&data[0..8]);