Apply clippy suggestions

This commit is contained in:
timvisee 2018-05-17 02:09:52 +02:00
parent f0ca016f4a
commit b62f3fd343
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
34 changed files with 126 additions and 119 deletions

View file

@ -24,7 +24,7 @@ impl<'a> Delete<'a> {
pub fn new(file: &'a RemoteFile, nonce: Option<Vec<u8>>) -> Self { pub fn new(file: &'a RemoteFile, nonce: Option<Vec<u8>>) -> Self {
Self { Self {
file, file,
nonce: nonce.unwrap_or(Vec::new()), nonce: nonce.unwrap_or_default(),
} }
} }
@ -42,7 +42,7 @@ impl<'a> Delete<'a> {
))?; ))?;
// Send the delete request // Send the delete request
self.request_delete(client, data).map_err(|err| err.into()) self.request_delete(client, &data)
} }
/// Fetch the authentication nonce for the file from the remote server. /// Fetch the authentication nonce for the file from the remote server.
@ -59,7 +59,7 @@ impl<'a> Delete<'a> {
fn request_delete( fn request_delete(
&self, &self,
client: &Client, client: &Client,
data: OwnedData<DeleteData>, data: &OwnedData<DeleteData>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Get the delete URL, and send the request // Get the delete URL, and send the request
let url = UrlBuilder::api_delete(self.file); let url = UrlBuilder::api_delete(self.file);
@ -77,13 +77,13 @@ impl<'a> Delete<'a> {
/// The delete data object. /// The delete data object.
/// This object is currently empty, as no additional data is sent to the /// This object is currently empty, as no additional data is sent to the
/// server. /// server.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize, Default)]
pub struct DeleteData { } pub struct DeleteData { }
impl DeleteData { impl DeleteData {
/// Constructor. /// Constructor.
pub fn new() -> Self { pub fn new() -> Self {
DeleteData { } DeleteData::default()
} }
} }

View file

@ -66,7 +66,7 @@ impl<'a> Download<'a> {
pub fn invoke( pub fn invoke(
mut self, mut self,
client: &Client, client: &Client,
reporter: Arc<Mutex<ProgressReporter>>, reporter: &Arc<Mutex<ProgressReporter>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Create a key set for the file // Create a key set for the file
let mut key = KeySet::from(self.file, self.password.as_ref()); let mut key = KeySet::from(self.file, self.password.as_ref());
@ -101,7 +101,7 @@ impl<'a> Download<'a> {
// Create the file reader for downloading // Create the file reader for downloading
let (reader, len) = self.create_file_reader( let (reader, len) = self.create_file_reader(
&key, &key,
metadata.nonce().to_vec(), metadata.nonce(),
&client, &client,
)?; )?;
@ -110,11 +110,11 @@ impl<'a> Download<'a> {
out, out,
len, len,
&key, &key,
reporter.clone(), &reporter,
).map_err(|err| Error::File(path_str.clone(), err))?; ).map_err(|err| Error::File(path_str.clone(), err))?;
// Download the file // Download the file
self.download(reader, writer, len, reporter)?; self.download(reader, writer, len, &reporter)?;
// TODO: return the file path // TODO: return the file path
// TODO: return the new remote state (does it still exist remote) // TODO: return the new remote state (does it still exist remote)
@ -160,7 +160,7 @@ impl<'a> Download<'a> {
fn create_file_reader( fn create_file_reader(
&self, &self,
key: &KeySet, key: &KeySet,
meta_nonce: Vec<u8>, meta_nonce: &[u8],
client: &Client, client: &Client,
) -> Result<(Response, u64), DownloadError> { ) -> Result<(Response, u64), DownloadError> {
// Compute the cryptographic signature // Compute the cryptographic signature
@ -177,7 +177,7 @@ impl<'a> Download<'a> {
// Ensure the response is succesful // Ensure the response is succesful
ensure_success(&response) ensure_success(&response)
.map_err(|err| DownloadError::Response(err))?; .map_err(DownloadError::Response)?;
// Get the content length // Get the content length
// TODO: make sure there is enough disk space // TODO: make sure there is enough disk space
@ -196,7 +196,7 @@ impl<'a> Download<'a> {
file: File, file: File,
len: u64, len: u64,
key: &KeySet, key: &KeySet,
reporter: Arc<Mutex<ProgressReporter>>, reporter: &Arc<Mutex<ProgressReporter>>,
) -> Result<ProgressWriter<EncryptedFileWriter>, FileError> { ) -> Result<ProgressWriter<EncryptedFileWriter>, FileError> {
// Build an encrypted writer // Build an encrypted writer
let mut writer = ProgressWriter::new( let mut writer = ProgressWriter::new(
@ -223,7 +223,7 @@ impl<'a> Download<'a> {
mut reader: R, mut reader: R,
mut writer: ProgressWriter<EncryptedFileWriter>, mut writer: ProgressWriter<EncryptedFileWriter>,
len: u64, len: u64,
reporter: Arc<Mutex<ProgressReporter>>, reporter: &Arc<Mutex<ProgressReporter>>,
) -> Result<(), DownloadError> { ) -> Result<(), DownloadError> {
// Start the writer // Start the writer
reporter.lock() reporter.lock()

View file

@ -29,7 +29,7 @@ impl<'a> Info<'a> {
pub fn new(file: &'a RemoteFile, nonce: Option<Vec<u8>>) -> Self { pub fn new(file: &'a RemoteFile, nonce: Option<Vec<u8>>) -> Self {
Self { Self {
file, file,
nonce: nonce.unwrap_or(Vec::new()), nonce: nonce.unwrap_or_default(),
} }
} }
@ -45,7 +45,7 @@ impl<'a> Info<'a> {
.map_err(|err| -> PrepareError { err.into() })?; .map_err(|err| -> PrepareError { err.into() })?;
// Send the info request // Send the info request
self.fetch_info(client, data).map_err(|err| err.into()) self.fetch_info(client, &data)
} }
/// Fetch the authentication nonce for the file from the remote server. /// Fetch the authentication nonce for the file from the remote server.
@ -62,7 +62,7 @@ impl<'a> Info<'a> {
fn fetch_info( fn fetch_info(
&self, &self,
client: &Client, client: &Client,
data: OwnedData<InfoData>, data: &OwnedData<InfoData>,
) -> Result<InfoResponse, Error> { ) -> Result<InfoResponse, Error> {
// Get the info URL, and send the request // Get the info URL, and send the request
let url = UrlBuilder::api_info(self.file); let url = UrlBuilder::api_info(self.file);
@ -87,13 +87,13 @@ impl<'a> Info<'a> {
/// The info data object. /// The info data object.
/// This object is currently empty, as no additional data is sent to the /// This object is currently empty, as no additional data is sent to the
/// server. /// server.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize, Default)]
pub struct InfoData { } pub struct InfoData { }
impl InfoData { impl InfoData {
/// Constructor. /// Constructor.
pub fn new() -> Self { pub fn new() -> Self {
InfoData { } InfoData::default()
} }
} }

View file

@ -56,19 +56,19 @@ impl<'a> Metadata<'a> {
} }
// Make sure a password is given when it is required // Make sure a password is given when it is required
if !self.password.is_some() && exist_response.has_password() { if self.password.is_none() && exist_response.has_password() {
return Err(Error::PasswordRequired); return Err(Error::PasswordRequired);
} }
} }
// Create a key set for the file // Create a key set for the file
let mut key = KeySet::from(self.file, self.password.as_ref()); let key = KeySet::from(self.file, self.password.as_ref());
// Fetch the authentication nonce // Fetch the authentication nonce
let auth_nonce = self.fetch_auth_nonce(client)?; let auth_nonce = self.fetch_auth_nonce(client)?;
// Fetch the metadata and the metadata nonce, return the result // Fetch the metadata and the metadata nonce, return the result
self.fetch_metadata(&client, &mut key, auth_nonce) self.fetch_metadata(&client, &key, &auth_nonce)
.map_err(|err| err.into()) .map_err(|err| err.into())
} }
@ -92,7 +92,7 @@ impl<'a> Metadata<'a> {
&self, &self,
client: &Client, client: &Client,
key: &KeySet, key: &KeySet,
auth_nonce: Vec<u8>, auth_nonce: &[u8],
) -> Result<MetadataResponse, MetaError> { ) -> Result<MetadataResponse, MetaError> {
// Compute the cryptographic signature for authentication // Compute the cryptographic signature for authentication
let sig = signature_encoded(key.auth_key().unwrap(), &auth_nonce) let sig = signature_encoded(key.auth_key().unwrap(), &auth_nonce)
@ -108,11 +108,11 @@ impl<'a> Metadata<'a> {
// Ensure the status code is successful // Ensure the status code is successful
ensure_success(&response) ensure_success(&response)
.map_err(|err| MetaError::NonceResponse(err))?; .map_err(MetaError::NonceResponse)?;
// Get the metadata nonce // Get the metadata nonce
let nonce = header_nonce(&response) let nonce = header_nonce(&response)
.map_err(|err| MetaError::Nonce(err))?; .map_err(MetaError::Nonce)?;
// Parse the metadata response // Parse the metadata response
MetadataResponse::from( MetadataResponse::from(

View file

@ -11,7 +11,7 @@ use file::remote_file::RemoteFile;
/// The default download count. /// The default download count.
pub const PARAMS_DEFAULT_DOWNLOAD: u8 = 1; pub const PARAMS_DEFAULT_DOWNLOAD: u8 = 1;
pub const PARAMS_DEFAULT_DOWNLOAD_STR: &'static str = "1"; pub const PARAMS_DEFAULT_DOWNLOAD_STR: &str = "1";
/// The minimum allowed number of downloads, enforced by the server. /// The minimum allowed number of downloads, enforced by the server.
pub const PARAMS_DOWNLOAD_MIN: u8 = 1; pub const PARAMS_DOWNLOAD_MIN: u8 = 1;
@ -43,7 +43,7 @@ impl<'a> Params<'a> {
Self { Self {
file, file,
params, params,
nonce: nonce.unwrap_or(Vec::new()), nonce: nonce.unwrap_or_default(),
} }
} }
@ -61,8 +61,7 @@ impl<'a> Params<'a> {
.map_err(|err| -> PrepareError { err.into() })?; .map_err(|err| -> PrepareError { err.into() })?;
// Send the request to change the parameters // Send the request to change the parameters
self.change_params(client, data) self.change_params(client, &data)
.map_err(|err| err.into())
} }
/// Fetch the authentication nonce for the file from the remote server. /// Fetch the authentication nonce for the file from the remote server.
@ -79,7 +78,7 @@ impl<'a> Params<'a> {
fn change_params( fn change_params(
&self, &self,
client: &Client, client: &Client,
data: OwnedData<ParamsData>, data: &OwnedData<ParamsData>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Get the params URL, and send the change // Get the params URL, and send the change
let url = UrlBuilder::api_params(self.file); let url = UrlBuilder::api_params(self.file);

View file

@ -33,7 +33,7 @@ impl<'a> Password<'a> {
Self { Self {
file, file,
password, password,
nonce: nonce.unwrap_or(Vec::new()), nonce: nonce.unwrap_or_default(),
} }
} }
@ -55,8 +55,7 @@ impl<'a> Password<'a> {
.map_err(|err| -> PrepareError { err.into() })?; .map_err(|err| -> PrepareError { err.into() })?;
// Send the request to change the password // Send the request to change the password
self.change_password(client, data) self.change_password(client, &data)
.map_err(|err| err.into())
} }
/// Fetch the authentication nonce for the file from the Send server. /// Fetch the authentication nonce for the file from the Send server.
@ -73,7 +72,7 @@ impl<'a> Password<'a> {
fn change_password( fn change_password(
&self, &self,
client: &Client, client: &Client,
data: OwnedData<PasswordData>, data: &OwnedData<PasswordData>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Get the password URL, and send the change // Get the password URL, and send the change
let url = UrlBuilder::api_password(self.file); let url = UrlBuilder::api_password(self.file);

View file

@ -86,7 +86,7 @@ impl Upload {
pub fn invoke( pub fn invoke(
self, self,
client: &Client, client: &Client,
reporter: Arc<Mutex<ProgressReporter>>, reporter: &Arc<Mutex<ProgressReporter>>,
) -> Result<RemoteFile, Error> { ) -> Result<RemoteFile, Error> {
// Create file data, generate a key // Create file data, generate a key
let file = FileData::from(&self.path)?; let file = FileData::from(&self.path)?;
@ -101,7 +101,7 @@ impl Upload {
let req = self.create_request( let req = self.create_request(
client, client,
&key, &key,
metadata, &metadata,
reader, reader,
); );
@ -137,13 +137,13 @@ impl Upload {
{ {
// Determine what filename to use // Determine what filename to use
let name = self.name.clone() let name = self.name.clone()
.unwrap_or(file.name().to_owned()); .unwrap_or_else(|| file.name().to_owned());
// Construct the metadata // Construct the metadata
let metadata = Metadata::from( let metadata = Metadata::from(
key.iv(), key.iv(),
name, name,
file.mime().clone(), &file.mime(),
).to_json().into_bytes(); ).to_json().into_bytes();
// Encrypt the metadata // Encrypt the metadata
@ -207,7 +207,7 @@ impl Upload {
&self, &self,
client: &Client, client: &Client,
key: &KeySet, key: &KeySet,
metadata: Vec<u8>, metadata: &[u8],
reader: EncryptedReader, reader: EncryptedReader,
) -> Request { ) -> Request {
// Get the reader length // Get the reader length
@ -250,7 +250,7 @@ impl Upload {
// Ensure the response is successful // Ensure the response is successful
ensure_success(&response) ensure_success(&response)
.map_err(|err| UploadError::Response(err))?; .map_err(UploadError::Response)?;
// Try to get the nonce, don't error on failure // Try to get the nonce, don't error on failure
let nonce = header_nonce(&response).ok(); let nonce = header_nonce(&response).ok();

View file

@ -5,7 +5,7 @@ use api::request::{ensure_success, ResponseError};
use crypto::b64; use crypto::b64;
/// The name of the header the nonce is delivered in. /// The name of the header the nonce is delivered in.
const HEADER_NONCE: &'static str = "WWW-Authenticate"; const HEADER_NONCE: &str = "WWW-Authenticate";
/// Do a new request, and extract the nonce from a header in the given /// Do a new request, and extract the nonce from a header in the given
/// response. /// response.
@ -38,11 +38,10 @@ pub fn header_nonce(response: &Response)
.and_then(|line| String::from_utf8(line.to_vec()) .and_then(|line| String::from_utf8(line.to_vec())
.map_err(|_| NonceError::MalformedNonce) .map_err(|_| NonceError::MalformedNonce)
)? )?
.split_terminator(" ") .split_terminator(' ')
.skip(1) .nth(2)
.next()
.ok_or(NonceError::MalformedNonce)? .ok_or(NonceError::MalformedNonce)?
).map_err(|_| NonceError::MalformedNonce.into()) ).map_err(|_| NonceError::MalformedNonce)
} }
#[derive(Fail, Debug)] #[derive(Fail, Debug)]

View file

@ -1,7 +1,7 @@
use reqwest::StatusCode; use reqwest::StatusCode;
/// The Send host to use by default. /// The Send host to use by default.
pub const SEND_DEFAULT_HOST: &'static str = "https://send.firefox.com/"; pub const SEND_DEFAULT_HOST: &str = "https://send.firefox.com/";
/// The default time after which uploaded files expire after, in seconds. /// The default time after which uploaded files expire after, in seconds.
pub const SEND_DEFAULT_EXPIRE_TIME: i64 = 24 * 60 * 60; pub const SEND_DEFAULT_EXPIRE_TIME: i64 = 24 * 60 * 60;
@ -13,7 +13,7 @@ pub const HTTP_STATUS_EXPIRED: StatusCode = StatusCode::NotFound;
pub const HTTP_STATUS_UNAUTHORIZED: StatusCode = StatusCode::Unauthorized; pub const HTTP_STATUS_UNAUTHORIZED: StatusCode = StatusCode::Unauthorized;
/// The recommended maximum upload size in bytes. /// The recommended maximum upload size in bytes.
pub const UPLOAD_SIZE_MAX_RECOMMENDED: u64 = 1024 * 1024 * 1024 * 1; pub const UPLOAD_SIZE_MAX_RECOMMENDED: u64 = 1024 * 1024 * 1024;
/// The maximum upload size in bytes. /// The maximum upload size in bytes.
pub const UPLOAD_SIZE_MAX: u64 = 1024 * 1024 * 1024 * 2; pub const UPLOAD_SIZE_MAX: u64 = 1024 * 1024 * 1024 * 2;

View file

@ -26,7 +26,7 @@ const KEY_AUTH_ITERATIONS: usize = 100;
/// # Returns /// # Returns
/// The output keying material, with the length as as specified in the `length` /// The output keying material, with the length as as specified in the `length`
/// argument. /// argument.
fn hkdf<'a>( fn hkdf(
length: usize, length: usize,
ikm: &[u8], ikm: &[u8],
info: Option<&[u8]>, info: Option<&[u8]>,

View file

@ -10,6 +10,6 @@ impl StatusCodeExt for StatusCode {
fn err_text(&self) -> String { fn err_text(&self) -> String {
self.canonical_reason() self.canonical_reason()
.map(|text| format!("{} {}", self.as_u16(), text)) .map(|text| format!("{} {}", self.as_u16(), text))
.unwrap_or(format!("{}", self.as_u16())) .unwrap_or_else(|| format!("{}", self.as_u16()))
} }
} }

View file

@ -34,7 +34,7 @@ impl Metadata {
/// * iv: initialisation vector /// * iv: initialisation vector
/// * name: file name /// * name: file name
/// * mime: file mimetype /// * mime: file mimetype
pub fn from(iv: &[u8], name: String, mime: Mime) -> Self { pub fn from(iv: &[u8], name: String, mime: &Mime) -> Self {
Metadata { Metadata {
iv: b64::encode(iv), iv: b64::encode(iv),
name, name,

View file

@ -17,11 +17,11 @@ use crypto::b64;
// TODO: match any sub-path? // TODO: match any sub-path?
// TODO: match URL-safe base64 chars for the file ID? // TODO: match URL-safe base64 chars for the file ID?
// TODO: constrain the ID length? // TODO: constrain the ID length?
const SHARE_PATH_PATTERN: &'static str = r"^/?download/([[:alnum:]]{8,}={0,3})/?$"; const SHARE_PATH_PATTERN: &str = r"^/?download/([[:alnum:]]{8,}={0,3})/?$";
/// A pattern for share URL fragments, capturing the file secret. /// A pattern for share URL fragments, capturing the file secret.
// TODO: constrain the secret length? // TODO: constrain the secret length?
const SHARE_FRAGMENT_PATTERN: &'static str = r"^([a-zA-Z0-9-_+/]+)?\s*$"; const SHARE_FRAGMENT_PATTERN: &str = r"^([a-zA-Z0-9-_+/]+)?\s*$";
/// A struct representing an uploaded file on a Send host. /// A struct representing an uploaded file on a Send host.
/// ///
@ -289,19 +289,20 @@ impl RemoteFile {
/// This is ofcourse only done for properties that may be empty. /// This is ofcourse only done for properties that may be empty.
/// ///
/// The file IDs are not asserted for equality. /// The file IDs are not asserted for equality.
#[allow(useless_let_if_seq)]
pub fn merge(&mut self, other: &RemoteFile, overwrite: bool) -> bool { pub fn merge(&mut self, other: &RemoteFile, overwrite: bool) -> bool {
// Remember whether anything was changed // Remember whether anything has changed
let mut changed = false; let mut changed = false;
// Set the upload time // Set the upload time
if other.upload_at.is_some() && (self.upload_at.is_none() || overwrite) { if other.upload_at.is_some() && (self.upload_at.is_none() || overwrite) {
self.upload_at = other.upload_at.clone(); self.upload_at = other.upload_at;
changed = true; changed = true;
} }
// Set the expire time // Set the expire time
if !other.expire_uncertain() && (self.expire_uncertain() || overwrite) { if !other.expire_uncertain() && (self.expire_uncertain() || overwrite) {
self.expire_at = other.expire_at.clone(); self.expire_at = other.expire_at;
self.expire_uncertain = other.expire_uncertain(); self.expire_uncertain = other.expire_uncertain();
changed = true; changed = true;
} }
@ -318,7 +319,7 @@ impl RemoteFile {
changed = true; changed = true;
} }
return changed; changed
} }
} }

View file

@ -94,7 +94,7 @@ impl EncryptedFileReader {
/// returned. /// returned.
fn read_internal(&mut self, buf: &mut [u8]) -> usize { fn read_internal(&mut self, buf: &mut [u8]) -> usize {
// Return if there is no data to read // Return if there is no data to read
if self.internal_buf.is_empty() || buf.len() == 0 { if self.internal_buf.is_empty() || buf.is_empty() {
return 0; return 0;
} }
@ -335,6 +335,11 @@ pub trait ProgressReporter: Send {
pub trait ExactLengthReader { pub trait ExactLengthReader {
/// Get the exact length of the reader in bytes. /// Get the exact length of the reader in bytes.
fn len(&self) -> Result<u64, io::Error>; fn len(&self) -> Result<u64, io::Error>;
/// Check whehter this extact length reader is emtpy.
fn is_empty(&self) -> Result<bool, io::Error> {
self.len().map(|l| l == 0)
}
} }
impl<R: ExactLengthReader + Read> ExactLengthReader for BufReader<R> { impl<R: ExactLengthReader + Read> ExactLengthReader for BufReader<R> {

View file

@ -18,6 +18,7 @@ use ffsend_api::action::metadata::{
Metadata as ApiMetadata, Metadata as ApiMetadata,
}; };
use ffsend_api::file::remote_file::{FileParseError, RemoteFile}; use ffsend_api::file::remote_file::{FileParseError, RemoteFile};
use ffsend_api::reader::ProgressReporter;
use ffsend_api::reqwest::Client; use ffsend_api::reqwest::Client;
use cmd::matcher::{ use cmd::matcher::{
@ -93,7 +94,7 @@ impl<'a> Download<'a> {
// Prepare the output path to use // Prepare the output path to use
let target = Self::prepare_path( let target = Self::prepare_path(
target, &target,
metadata.metadata().name(), metadata.metadata().name(),
&matcher_main, &matcher_main,
); );
@ -104,7 +105,8 @@ impl<'a> Download<'a> {
} }
// Create a progress bar reporter // Create a progress bar reporter
let bar = Arc::new(Mutex::new(ProgressBar::new_download())); let progress_bar = Arc::new(Mutex::new(ProgressBar::new_download()));
let progress_reader: Arc<Mutex<ProgressReporter>> = progress_bar;
// Execute an download action // Execute an download action
ApiDownload::new( ApiDownload::new(
@ -113,7 +115,7 @@ impl<'a> Download<'a> {
password, password,
false, false,
Some(metadata), Some(metadata),
).invoke(&client, bar)?; ).invoke(&client, &progress_reader)?;
// Add the file to the history // Add the file to the history
#[cfg(feature = "history")] #[cfg(feature = "history")]
@ -138,12 +140,12 @@ impl<'a> Download<'a> {
/// ///
/// The program will quit with an error message if a problem occurs. /// The program will quit with an error message if a problem occurs.
fn prepare_path( fn prepare_path(
target: PathBuf, target: &PathBuf,
name_hint: &str, name_hint: &str,
main_matcher: &MainMatcher, main_matcher: &MainMatcher,
) -> PathBuf { ) -> PathBuf {
// Select the path to use // Select the path to use
let target = Self::select_path(target, name_hint); let target = Self::select_path(&target, name_hint);
// Ask to overwrite // Ask to overwrite
if target.exists() && !main_matcher.force() { if target.exists() && !main_matcher.force() {
@ -185,7 +187,7 @@ impl<'a> Download<'a> {
), ),
} }
return target; target
} }
/// This methods prepares a full file path to use for the file to /// This methods prepares a full file path to use for the file to
@ -195,7 +197,7 @@ impl<'a> Download<'a> {
/// If no file name was given, the original file name is used. /// If no file name was given, the original file name is used.
/// ///
/// The full path including the file name will be returned. /// The full path including the file name will be returned.
fn select_path(target: PathBuf, name_hint: &str) -> PathBuf { fn select_path(target: &PathBuf, name_hint: &str) -> PathBuf {
// If we're already working with a file, canonicalize and return // If we're already working with a file, canonicalize and return
if target.is_file() { if target.is_file() {
match target.canonicalize() { match target.canonicalize() {
@ -255,7 +257,7 @@ impl<'a> Download<'a> {
} }
} }
return target; target
} }
} }

View file

@ -15,6 +15,7 @@ use ffsend_api::action::upload::{
Upload as ApiUpload, Upload as ApiUpload,
}; };
use ffsend_api::config::{UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_RECOMMENDED}; use ffsend_api::config::{UPLOAD_SIZE_MAX, UPLOAD_SIZE_MAX_RECOMMENDED};
use ffsend_api::reader::ProgressReporter;
use ffsend_api::reqwest::Client; use ffsend_api::reqwest::Client;
use self::tempfile::{ use self::tempfile::{
Builder as TempBuilder, Builder as TempBuilder,
@ -106,7 +107,7 @@ impl<'a> Upload<'a> {
let client = Client::new(); let client = Client::new();
// Create a progress bar reporter // Create a progress bar reporter
let bar = Arc::new(Mutex::new(ProgressBar::new_upload())); let progress_bar = Arc::new(Mutex::new(ProgressBar::new_upload()));
// Build a parameters object to set for the file // Build a parameters object to set for the file
let params = { let params = {
@ -142,14 +143,14 @@ impl<'a> Upload<'a> {
.prefix(&format!(".{}-archive-", crate_name!())) .prefix(&format!(".{}-archive-", crate_name!()))
.suffix(archive_extention) .suffix(archive_extention)
.tempfile() .tempfile()
.map_err(|err| ArchiveError::TempFile(err))? .map_err(ArchiveError::TempFile)?
); );
if let Some(tmp_archive) = &tmp_archive { if let Some(tmp_archive) = &tmp_archive {
// Get the path, and the actual file // Get the path, and the actual file
let archive_path = tmp_archive.path().clone().to_path_buf(); let archive_path = tmp_archive.path().to_path_buf();
let archive_file = tmp_archive.as_file() let archive_file = tmp_archive.as_file()
.try_clone() .try_clone()
.map_err(|err| ArchiveError::CloneHandle(err))?; .map_err(ArchiveError::CloneHandle)?;
// Select the file name to use if not set // Select the file name to use if not set
if file_name.is_none() { if file_name.is_none() {
@ -166,10 +167,10 @@ impl<'a> Upload<'a> {
// Build an archiver and append the file // Build an archiver and append the file
let mut archiver = Archiver::new(archive_file); let mut archiver = Archiver::new(archive_file);
archiver.append_path(file_name.as_ref().unwrap(), &path) archiver.append_path(file_name.as_ref().unwrap(), &path)
.map_err(|err| ArchiveError::AddFile(err))?; .map_err(ArchiveError::AddFile)?;
// Finish the archival process, writes the archive file // Finish the archival process, writes the archive file
archiver.finish().map_err(|err| ArchiveError::Write(err))?; archiver.finish().map_err(ArchiveError::Write)?;
// Append archive extention to name, set to upload archived file // Append archive extention to name, set to upload archived file
if let Some(ref mut file_name) = file_name { if let Some(ref mut file_name) = file_name {
@ -179,6 +180,9 @@ impl<'a> Upload<'a> {
} }
} }
// Build the progress reporter
let progress_reporter: Arc<Mutex<ProgressReporter>> = progress_bar;
// Execute an upload action // Execute an upload action
let file = ApiUpload::new( let file = ApiUpload::new(
host, host,
@ -186,7 +190,7 @@ impl<'a> Upload<'a> {
file_name, file_name,
matcher_upload.password(), matcher_upload.password(),
params, params,
).invoke(&client, bar)?; ).invoke(&client, &progress_reporter)?;
// Get the download URL, and report it in the console // Get the download URL, and report it in the console
let url = file.download_url(true); let url = file.download_url(true);
@ -199,7 +203,7 @@ impl<'a> Upload<'a> {
// Open the URL in the browser // Open the URL in the browser
if matcher_upload.open() { if matcher_upload.open() {
if let Err(err) = open_url(url.clone()) { if let Err(err) = open_url(&url) {
print_error( print_error(
err.context("failed to open the URL in the browser") err.context("failed to open the URL in the browser")
); );
@ -209,12 +213,10 @@ impl<'a> Upload<'a> {
// Copy the URL in the user's clipboard // Copy the URL in the user's clipboard
#[cfg(feature = "clipboard")] #[cfg(feature = "clipboard")]
{ {
if matcher_upload.copy() { if matcher_upload.copy() && set_clipboard(url.as_str().to_owned()).is_err() {
if set_clipboard(url.as_str().to_owned()).is_err() {
print_error_msg("failed to copy the URL to the clipboard"); print_error_msg("failed to copy the URL to the clipboard");
} }
} }
}
// Close the temporary zip file, to ensure it's removed // Close the temporary zip file, to ensure it's removed
if let Some(tmp_archive) = tmp_archive.take() { if let Some(tmp_archive) = tmp_archive.take() {

View file

@ -14,7 +14,7 @@ use super::matcher::{
}; };
#[cfg(feature = "history")] #[cfg(feature = "history")]
use super::matcher::HistoryMatcher; use super::matcher::HistoryMatcher;
use super::cmd::{ use super::subcmd::{
CmdDelete, CmdDelete,
CmdDownload, CmdDownload,
CmdExists, CmdExists,
@ -24,7 +24,7 @@ use super::cmd::{
CmdUpload, CmdUpload,
}; };
#[cfg(feature = "history")] #[cfg(feature = "history")]
use super::cmd::CmdHistory; use super::subcmd::CmdHistory;
#[cfg(feature = "history")] #[cfg(feature = "history")]
use util::app_history_file_path_string; use util::app_history_file_path_string;

View file

@ -32,8 +32,8 @@ impl<'a: 'b, 'b> DownloadMatcher<'a> {
/// will be used. /// will be used.
pub fn output(&'a self) -> PathBuf { pub fn output(&'a self) -> PathBuf {
self.matches.value_of("output") self.matches.value_of("output")
.map(|path| PathBuf::from(path)) .map(PathBuf::from)
.unwrap_or(PathBuf::from("./")) .unwrap_or_else(|| PathBuf::from("./"))
} }
} }

View file

@ -33,7 +33,7 @@ impl<'a: 'b, 'b> MainMatcher<'a> {
pub fn history(&self) -> PathBuf { pub fn history(&self) -> PathBuf {
// Get the path // Get the path
let path = self.matches.value_of("history") let path = self.matches.value_of("history")
.map(|path| PathBuf::from(path)); .map(PathBuf::from);
// Ensure the path is correct // Ensure the path is correct
match path { match path {

View file

@ -1,5 +1,5 @@
pub mod arg; pub mod arg;
pub mod cmd; pub mod subcmd;
pub mod handler; pub mod handler;
pub mod matcher; pub mod matcher;

View file

@ -17,10 +17,10 @@ use self::version_compare::{
use util::{print_error, print_warning}; use util::{print_error, print_warning};
/// The minimum supported history file version. /// The minimum supported history file version.
const VERSION_MIN: &'static str = "0.0.1"; const VERSION_MIN: &str = "0.0.1";
/// The maximum supported history file version. /// The maximum supported history file version.
const VERSION_MAX: &'static str = crate_version!(); const VERSION_MAX: &str = crate_version!();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct History { pub struct History {
@ -105,7 +105,7 @@ impl History {
if self.files.is_empty() { if self.files.is_empty() {
if path.is_file() { if path.is_file() {
fs::remove_file(&path) fs::remove_file(&path)
.map_err(|err| SaveError::Delete(err))?; .map_err(SaveError::Delete)?;
} }
return Ok(()); return Ok(());
} }
@ -189,9 +189,7 @@ impl History {
/// If multiple files exist within the history that are equal, only one is returned. /// If multiple files exist within the history that are equal, only one is returned.
/// If no matching file was found, `None` is returned. /// If no matching file was found, `None` is returned.
pub fn get_file(&self, file: &RemoteFile) -> Option<&RemoteFile> { pub fn get_file(&self, file: &RemoteFile) -> Option<&RemoteFile> {
self.files.iter() self.files.iter().find(|f| f.id() == file.id() && f.host() == file.host())
.filter(|f| f.id() == file.id() && f.host() == file.host())
.next()
} }
/// Garbage collect (remove) all files that have been expired, /// Garbage collect (remove) all files that have been expired,

View file

@ -125,8 +125,8 @@ pub fn derive_file_properties(matcher_main: &MainMatcher, file: &mut RemoteFile)
} }
// Return whether any property was derived // Return whether any property was derived
return f.has_secret() || f.has_owner_token(); f.has_secret() || f.has_owner_token()
}, },
None => return false, None => false,
} }
} }

View file

@ -121,13 +121,13 @@ pub fn print_main_info() {
// Print the main info // Print the main info
println!("{} {}", crate_name!(), crate_version!()); println!("{} {}", crate_name!(), crate_version!());
println!("Usage: {} [FLAGS] <SUBCOMMAND> ...", exe); println!("Usage: {} [FLAGS] <SUBCOMMAND> ...", exe);
println!(""); println!();
println!("{}", crate_description!()); println!(crate_description!());
println!(""); println!();
println!("Missing subcommand. Here are the most used:"); println!("Missing subcommand. Here are the most used:");
println!(" {}", highlight(&format!("{} upload <FILE> ...", exe))); println!(" {}", highlight(&format!("{} upload <FILE> ...", exe)));
println!(" {}", highlight(&format!("{} download <URL> ...", exe))); println!(" {}", highlight(&format!("{} download <URL> ...", exe)));
println!(""); println!();
println!("To show all subcommands, features and other help:"); println!("To show all subcommands, features and other help:");
println!(" {}", highlight(&format!("{} help [SUBCOMMAND]", exe))); println!(" {}", highlight(&format!("{} help [SUBCOMMAND]", exe)));
} }

View file

@ -14,7 +14,7 @@ const PROGRESS_BAR_FPS_MILLIS: u64 = 200;
/// A progress bar reporter. /// A progress bar reporter.
pub struct ProgressBar<'a> { pub struct ProgressBar<'a> {
bar: Option<Pbr<Stdout>>, progress_bar: Option<Pbr<Stdout>>,
msg_progress: &'a str, msg_progress: &'a str,
msg_finish: &'a str, msg_finish: &'a str,
} }
@ -23,7 +23,7 @@ impl<'a> ProgressBar<'a> {
/// Construct a new progress bar, with the given messages. /// Construct a new progress bar, with the given messages.
pub fn new(msg_progress: &'a str, msg_finish: &'a str) -> ProgressBar<'a> { pub fn new(msg_progress: &'a str, msg_finish: &'a str) -> ProgressBar<'a> {
Self { Self {
bar: None, progress_bar: None,
msg_progress, msg_progress,
msg_finish, msg_finish,
} }
@ -44,26 +44,26 @@ impl<'a> ProgressReporter for ProgressBar<'a> {
/// Start the progress with the given total. /// Start the progress with the given total.
fn start(&mut self, total: u64) { fn start(&mut self, total: u64) {
// Initialize the progress bar // Initialize the progress bar
let mut bar = Pbr::new(total); let mut progress_bar = Pbr::new(total);
bar.set_max_refresh_rate( progress_bar.set_max_refresh_rate(
Some(Duration::from_millis(PROGRESS_BAR_FPS_MILLIS)) Some(Duration::from_millis(PROGRESS_BAR_FPS_MILLIS))
); );
bar.set_units(Units::Bytes); progress_bar.set_units(Units::Bytes);
bar.message(self.msg_progress); progress_bar.message(self.msg_progress);
self.bar = Some(bar); self.progress_bar = Some(progress_bar);
} }
/// A progress update. /// A progress update.
fn progress(&mut self, progress: u64) { fn progress(&mut self, progress: u64) {
self.bar.as_mut() self.progress_bar.as_mut()
.expect("progress bar not yet instantiated, cannot set progress") .expect("progress bar not yet instantiated, cannot set progress")
.set(progress); .set(progress);
} }
/// Finish the progress. /// Finish the progress.
fn finish(&mut self) { fn finish(&mut self) {
self.bar.as_mut() self.progress_bar.as_mut()
.expect("progress bar not yet instantiated") .expect("progress bar not yet instantiated")
.finish_print(self.msg_finish); .finish_print(self.msg_finish);
} }

View file

@ -5,6 +5,7 @@ extern crate directories;
extern crate fs2; extern crate fs2;
extern crate open; extern crate open;
use std::borrow::Borrow;
use std::env::current_exe; use std::env::current_exe;
#[cfg(feature = "clipboard")] #[cfg(feature = "clipboard")]
use std::error::Error as StdError; use std::error::Error as StdError;
@ -40,9 +41,11 @@ pub fn print_success(msg: &str) {
/// Print the given error in a proper format for the user, /// Print the given error in a proper format for the user,
/// with it's causes. /// with it's causes.
pub fn print_error<E: Fail>(err: E) { pub fn print_error<E: Fail>(err: impl Borrow<E>) {
// Report each printable error, count them // Report each printable error, count them
let count = err.causes() .map(|err| format!("{}", err)) let count = err.borrow()
.causes()
.map(|err| format!("{}", err))
.filter(|err| !err.is_empty()) .filter(|err| !err.is_empty())
.enumerate() .enumerate()
.map(|(i, err)| if i == 0 { .map(|(i, err)| if i == 0 {
@ -57,7 +60,6 @@ pub fn print_error<E: Fail>(err: E) {
eprintln!("{} {}", highlight_error("error:"), "an undefined error occurred"); eprintln!("{} {}", highlight_error("error:"), "an undefined error occurred");
} }
} }
/// Print the given error message in a proper format for the user, /// Print the given error message in a proper format for the user,
/// with it's causes. /// with it's causes.
pub fn print_error_msg<S>(err: S) pub fn print_error_msg<S>(err: S)
@ -83,12 +85,12 @@ pub fn quit() -> ! {
/// Quit the application with an error code, /// Quit the application with an error code,
/// and print the given error. /// and print the given error.
pub fn quit_error<E: Fail>(err: E, hints: ErrorHints) -> ! { pub fn quit_error<E: Fail>(err: E, hints: impl Borrow<ErrorHints>) -> ! {
// Print the error // Print the error
print_error(err); print_error(err);
// Print error hints // Print error hints
hints.print(); hints.borrow().print();
// Quit // Quit
exit(1); exit(1);
@ -96,7 +98,7 @@ pub fn quit_error<E: Fail>(err: E, hints: ErrorHints) -> ! {
/// Quit the application with an error code, /// Quit the application with an error code,
/// and print the given error message. /// and print the given error message.
pub fn quit_error_msg<S>(err: S, hints: ErrorHints) -> ! pub fn quit_error_msg<S>(err: S, hints: impl Borrow<ErrorHints>) -> !
where where
S: AsRef<str> + Display + Debug + Sync + Send + 'static S: AsRef<str> + Display + Debug + Sync + Send + 'static
{ {
@ -247,8 +249,8 @@ pub fn highlight_info(msg: &str) -> ColoredString {
/// Open the given URL in the users default browser. /// Open the given URL in the users default browser.
/// The browsers exit statis is returned. /// The browsers exit statis is returned.
pub fn open_url(url: Url) -> Result<ExitStatus, IoError> { pub fn open_url(url: impl Borrow<Url>) -> Result<ExitStatus, IoError> {
open_path(url.as_str()) open_path(url.borrow().as_str())
} }
/// Open the given path or URL using the program configured on the system. /// Open the given path or URL using the program configured on the system.
@ -538,15 +540,15 @@ pub fn format_duration(duration: &Duration) -> String {
// Build a list of time units, define a list for time components // Build a list of time units, define a list for time components
let mut components = Vec::new(); let mut components = Vec::new();
let units = [ let units = [
(1 * 60 * 60 * 24 * 7, "w"), (60 * 60 * 24 * 7, "w"),
(1 * 60 * 60 * 24, "d"), (60 * 60 * 24, "d"),
(1 * 60 * 60, "h"), (60 * 60, "h"),
(1 * 60, "m"), (60, "m"),
(1, "s"), (1, "s"),
]; ];
// Fill the list of time components based on the units which fit // Fill the list of time components based on the units which fit
for unit in units.iter() { for unit in &units {
if secs >= unit.0 { if secs >= unit.0 {
components.push(format!("{}{}", secs / unit.0, unit.1)); components.push(format!("{}{}", secs / unit.0, unit.1));
secs %= unit.0; secs %= unit.0;
@ -564,7 +566,7 @@ pub fn exe_name() -> String {
.ok() .ok()
.and_then(|p| p.file_name().map(|n| n.to_owned())) .and_then(|p| p.file_name().map(|n| n.to_owned()))
.and_then(|n| n.into_string().ok()) .and_then(|n| n.into_string().ok())
.unwrap_or(crate_name!().into()) .unwrap_or_else(|| crate_name!().into())
} }
/// Ensure that there is enough free disk space available at the given `path`, /// Ensure that there is enough free disk space available at the given `path`,
@ -620,7 +622,7 @@ pub fn app_project_dirs() -> ProjectDirs {
/// Get the default path to use for the history file. /// Get the default path to use for the history file.
#[cfg(feature = "history")] #[cfg(feature = "history")]
pub fn app_history_file_path<'a>() -> PathBuf { pub fn app_history_file_path() -> PathBuf {
app_project_dirs().cache_dir().join("history.toml") app_project_dirs().cache_dir().join("history.toml")
} }