imp: accept any string-like parameter

Use the power of the `AsRef` trait to take generic parameters for
several API functions. This makes the API more ergonomic because the
callers may pass in static `str` slices or references to owned `String`s
or even more exotic things like a `Cow`, all based on their particular
situation.

Update the tests and examples to use the most natural types they have
available.

Fixes #77. No existing code should break, as `&String` implements
`AsRef<str>` and `AsRef<Path>`
This commit is contained in:
Lyle Mantooth
2019-04-03 09:01:28 -04:00
parent de57b8fbdf
commit 108162fcf8
9 changed files with 24 additions and 16 deletions

View File

@@ -34,7 +34,7 @@ fn main() {
let authenticator = Authenticator::new(&secret, let authenticator = Authenticator::new(&secret,
DefaultAuthenticatorDelegate, DefaultAuthenticatorDelegate,
client, client,
DiskTokenStorage::new(&"token_store.json".to_string()) DiskTokenStorage::new("token_store.json")
.unwrap(), .unwrap(),
Some(FlowType::InstalledInteractive)); Some(FlowType::InstalledInteractive));
let client = hyper::Client::with_connector( let client = hyper::Client::with_connector(

View File

@@ -165,7 +165,7 @@ fn publish_stuff(methods: &PubsubMethods, message: &str) {
// If called as '.../service_account pub', act as publisher; if called as '.../service_account // If called as '.../service_account pub', act as publisher; if called as '.../service_account
// sub', act as subscriber. // sub', act as subscriber.
fn main() { fn main() {
let client_secret = oauth::service_account_key_from_file(&"pubsub-auth.json".to_string()) let client_secret = oauth::service_account_key_from_file("pubsub-auth.json")
.unwrap(); .unwrap();
let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())); let client = hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
let mut access = oauth::ServiceAccountAccess::new(client_secret, client); let mut access = oauth::ServiceAccountAccess::new(client_secret, client);

View File

@@ -238,8 +238,7 @@ where
} }
} }
RefreshResult::RefreshError(ref err_str, ref err_description) => { RefreshResult::RefreshError(ref err_str, ref err_description) => {
self.delegate self.delegate.token_refresh_failed(err_str, err_description);
.token_refresh_failed(&err_str, &err_description);
let storage_err = let storage_err =
match self.storage.set(scope_key, &scopes, None) { match self.storage.set(scope_key, &scopes, None) {
Ok(_) => String::new(), Ok(_) => String::new(),

View File

@@ -90,7 +90,11 @@ pub trait AuthenticatorDelegate {
/// Called if we could not acquire a refresh token for a reason possibly specified /// Called if we could not acquire a refresh token for a reason possibly specified
/// by the server. /// by the server.
/// This call is made for the delegate's information only. /// This call is made for the delegate's information only.
fn token_refresh_failed(&mut self, error: &String, error_description: &Option<String>) { fn token_refresh_failed<S: AsRef<str>>(
&mut self,
error: S,
error_description: &Option<String>,
) {
{ {
let _ = error; let _ = error;
} }
@@ -136,7 +140,11 @@ pub trait AuthenticatorDelegate {
/// We need the user to navigate to a URL using their browser and potentially paste back a code /// We need the user to navigate to a URL using their browser and potentially paste back a code
/// (or maybe not). Whether they have to enter a code depends on the InstalledFlowReturnMethod /// (or maybe not). Whether they have to enter a code depends on the InstalledFlowReturnMethod
/// used. /// used.
fn present_user_url(&mut self, url: &String, need_code: bool) -> Option<String> { fn present_user_url<S: AsRef<str> + fmt::Display>(
&mut self,
url: S,
need_code: bool,
) -> Option<String> {
if need_code { if need_code {
println!( println!(
"Please direct your browser to {}, follow the instructions and enter the \ "Please direct your browser to {}, follow the instructions and enter the \

View File

@@ -314,7 +314,7 @@ pub mod tests {
fn working_flow() { fn working_flow() {
use crate::helper::parse_application_secret; use crate::helper::parse_application_secret;
let appsecret = parse_application_secret(&TEST_APP_SECRET.to_string()).unwrap(); let appsecret = parse_application_secret(TEST_APP_SECRET).unwrap();
let mut flow = DeviceFlow::new( let mut flow = DeviceFlow::new(
hyper::Client::with_connector(<MockGoogleAuth as Default>::default()), hyper::Client::with_connector(<MockGoogleAuth as Default>::default()),
&appsecret, &appsecret,

View File

@@ -28,8 +28,9 @@ pub fn read_application_secret(path: &Path) -> io::Result<ApplicationSecret> {
} }
/// Read an application secret from a JSON string. /// Read an application secret from a JSON string.
pub fn parse_application_secret(secret: &String) -> io::Result<ApplicationSecret> { pub fn parse_application_secret<S: AsRef<str>>(secret: S) -> io::Result<ApplicationSecret> {
let result: serde_json::Result<ConsoleApplicationSecret> = serde_json::from_str(secret); let result: serde_json::Result<ConsoleApplicationSecret> =
serde_json::from_str(secret.as_ref());
match result { match result {
Err(e) => Err(io::Error::new( Err(e) => Err(io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
@@ -52,7 +53,7 @@ pub fn parse_application_secret(secret: &String) -> io::Result<ApplicationSecret
/// Read a service account key from a JSON file. You can download the JSON keys from the Google /// Read a service account key from a JSON file. You can download the JSON keys from the Google
/// Cloud Console or the respective console of your service provider. /// Cloud Console or the respective console of your service provider.
pub fn service_account_key_from_file(path: &String) -> io::Result<ServiceAccountKey> { pub fn service_account_key_from_file<S: AsRef<Path>>(path: S) -> io::Result<ServiceAccountKey> {
let mut key = String::new(); let mut key = String::new();
let mut file = fs::OpenOptions::new().read(true).open(path)?; let mut file = fs::OpenOptions::new().read(true).open(path)?;
file.read_to_string(&mut key)?; file.read_to_string(&mut key)?;

View File

@@ -166,7 +166,7 @@ mod tests {
#[test] #[test]
fn refresh_flow() { fn refresh_flow() {
let appsecret = parse_application_secret(&TEST_APP_SECRET.to_string()).unwrap(); let appsecret = parse_application_secret(TEST_APP_SECRET).unwrap();
let mut c = hyper::Client::with_connector(<MockGoogleRefresh as Default>::default()); let mut c = hyper::Client::with_connector(<MockGoogleRefresh as Default>::default());
let mut flow = RefreshFlow::new(&mut c); let mut flow = RefreshFlow::new(&mut c);

View File

@@ -351,7 +351,7 @@ mod tests {
//#[test] //#[test]
#[allow(dead_code)] #[allow(dead_code)]
fn test_service_account_e2e() { fn test_service_account_e2e() {
let key = service_account_key_from_file(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap(); let key = service_account_key_from_file(TEST_PRIVATE_KEY_PATH).unwrap();
let client = let client =
hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())); hyper::Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap()));
let mut acc = ServiceAccountAccess::new(key, client); let mut acc = ServiceAccountAccess::new(key, client);
@@ -364,7 +364,7 @@ mod tests {
#[test] #[test]
fn test_jwt_initialize_claims() { fn test_jwt_initialize_claims() {
let key = service_account_key_from_file(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap(); let key = service_account_key_from_file(TEST_PRIVATE_KEY_PATH).unwrap();
let scopes = vec!["scope1", "scope2", "scope3"]; let scopes = vec!["scope1", "scope2", "scope3"];
let claims = super::init_claims_from_key(&key, &scopes); let claims = super::init_claims_from_key(&key, &scopes);
@@ -384,7 +384,7 @@ mod tests {
#[test] #[test]
fn test_jwt_sign() { fn test_jwt_sign() {
let key = service_account_key_from_file(&TEST_PRIVATE_KEY_PATH.to_string()).unwrap(); let key = service_account_key_from_file(TEST_PRIVATE_KEY_PATH).unwrap();
let scopes = vec!["scope1", "scope2", "scope3"]; let scopes = vec!["scope1", "scope2", "scope3"];
let claims = super::init_claims_from_key(&key, &scopes); let claims = super::init_claims_from_key(&key, &scopes);
let jwt = super::JWT::new(claims); let jwt = super::JWT::new(claims);

View File

@@ -132,9 +132,9 @@ pub struct DiskTokenStorage {
} }
impl DiskTokenStorage { impl DiskTokenStorage {
pub fn new(location: &String) -> Result<DiskTokenStorage, io::Error> { pub fn new<S: AsRef<str>>(location: S) -> Result<DiskTokenStorage, io::Error> {
let mut dts = DiskTokenStorage { let mut dts = DiskTokenStorage {
location: location.clone(), location: location.as_ref().to_owned(),
tokens: HashMap::new(), tokens: HashMap::new(),
}; };