diff --git a/src/appstate.rs b/src/appstate.rs index 0b9dfc8..a481007 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use super::{ cli::Cli, - sharry::{Alias, ChunkState, FileChecked, FileUploading, Share, UploadError}, + sharry::{Alias, ChunkState, FileChecked, FileUploading, Share, SharryFile, UploadError}, }; #[derive(Serialize, Deserialize, Debug)] @@ -37,8 +37,8 @@ enum FileState { impl FileState { fn file_name(&self) -> &str { match self { - FileState::C(checked) => checked.file_name(), - FileState::U(uploading) => uploading.file_name(), + FileState::C(checked) => checked.name(), + FileState::U(uploading) => uploading.name(), } } @@ -145,7 +145,7 @@ impl AppState { )) .unwrap(), ) - .with_message(uploading.file_name().to_owned()) + .with_message(uploading.name().to_owned()) .with_position(uploading.offset()); bar.enable_steady_tick(Duration::from_millis(100)); diff --git a/src/sharry/file/checked.rs b/src/sharry/file/checked.rs index 77e6548..8df0d86 100644 --- a/src/sharry/file/checked.rs +++ b/src/sharry/file/checked.rs @@ -8,7 +8,7 @@ use log::debug; use serde::{Deserialize, Serialize}; use ureq::http::StatusCode; -use super::{Alias, FileUploading, Share, SharryAlias}; +use super::{Alias, FileUploading, Share, SharryAlias, SharryFile}; #[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct FileChecked { @@ -30,30 +30,23 @@ impl FileChecked { } } - pub fn file_name(&self) -> &str { - self.path - .file_name() - .and_then(OsStr::to_str) - .expect("bad file name") - } - pub fn start_upload( self, http: &ureq::Agent, alias: &Alias, share: &Share, ) -> io::Result { - let size = usize::try_from(fs::metadata(&self.path)?.len()).map_err(io::Error::other)?; + let size: usize = self.size(); let res = { let endpoint = alias.get_endpoint(format!("alias/upload/{}/files/tus", share.id)); (http.post(endpoint)) .sharry_header(alias) - .header("Sharry-File-Name", self.file_name()) + .header("Sharry-File-Name", self.name()) .header("Upload-Length", size) .send_empty() - .map_err(io::Error::other)? + .map_err(ureq::Error::into_io)? }; if res.status() != StatusCode::CREATED { @@ -71,3 +64,29 @@ impl FileChecked { Ok(FileUploading::new(self.path, size, location)) } } + +impl<'t> SharryFile<'t> for FileChecked { + /// get a reference to the file's name + /// + /// Uses SharryFile::extract_file_name, which may **panic**! + fn name(&'t self) -> &'t str { + ::extract_file_name(&self.path) + } + + fn offset(&self) -> T + where + T: TryFrom, + >::Error: std::fmt::Debug + std::fmt::Display, + { + ::from_usize(0) + } + + fn size(&self) -> T + where + T: TryFrom, + >::Error: std::fmt::Debug + std::fmt::Display, + { + let val = ::to_usize(fs::metadata(&self.path).unwrap().len()); + ::from_usize(val) + } +} diff --git a/src/sharry/file/filetrait.rs b/src/sharry/file/filetrait.rs new file mode 100644 index 0000000..848a620 --- /dev/null +++ b/src/sharry/file/filetrait.rs @@ -0,0 +1,50 @@ +use std::{ + ffi::OsStr, + fmt::{Debug, Display}, + path::{Path, PathBuf}, +}; + +pub trait SharryFile<'t> { + /// get a reference to the filename from a PathBuf reference + /// + /// # Panics + /// + /// Expects `Path::file_name` and `ffi::OsStr::to_str` to succeed on the contained path. + fn extract_file_name(p: &'t PathBuf) -> &'t str { + p.file_name() + .and_then(OsStr::to_str) + .expect("bad file name") + } + + fn from_usize(val: usize) -> T + where + T: TryFrom, + >::Error: Debug + Display, + { + val.try_into() + .inspect_err(|e| panic!("usize did not fit into other type: {e}")) + .unwrap() + } + + fn to_usize(val: T) -> usize + where + T: TryInto, + >::Error: Debug + Display, + { + val.try_into() + .inspect_err(|e| panic!("usize did not fit into other type: {e}")) + .unwrap() + } + + fn name(&'t self) -> &'t str; + + fn offset(&self) -> T + where + T: TryFrom, + >::Error: Debug + Display; + + fn size(&self) -> T + where + T: TryFrom, + >::Error: Debug + Display; +} diff --git a/src/sharry/file/mod.rs b/src/sharry/file/mod.rs index 4614561..ae5ba78 100644 --- a/src/sharry/file/mod.rs +++ b/src/sharry/file/mod.rs @@ -1,7 +1,9 @@ mod checked; +mod filetrait; mod uploading; pub use checked::FileChecked; +pub use filetrait::SharryFile; pub use uploading::{ChunkState, FileUploading, UploadError}; use super::{Alias, Share, alias::SharryAlias}; diff --git a/src/sharry/file/uploading.rs b/src/sharry/file/uploading.rs index 048ece4..d3898e2 100644 --- a/src/sharry/file/uploading.rs +++ b/src/sharry/file/uploading.rs @@ -1,6 +1,5 @@ use std::{ ffi::OsStr, - fmt::{Debug, Display}, fs, io::{self, Read, Seek, SeekFrom}, path::PathBuf, @@ -10,7 +9,7 @@ use log::debug; use serde::{Deserialize, Serialize}; use ureq::http::{HeaderValue, StatusCode}; -use super::{Alias, SharryAlias}; +use super::{Alias, SharryAlias, SharryFile}; #[derive(Serialize, Deserialize, Debug)] pub struct FileUploading { @@ -34,7 +33,7 @@ pub enum ChunkState { Finished(PathBuf), } -impl Display for FileUploading { +impl std::fmt::Display for FileUploading { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -69,29 +68,6 @@ impl FileUploading { Ok(bytes) } - pub fn file_name(&self) -> &str { - self.path - .file_name() - .and_then(OsStr::to_str) - .expect("bad file name") - } - - pub fn offset(&self) -> T - where - T: TryFrom, - >::Error: Debug, - { - self.offset.try_into().unwrap() - } - - pub fn size(&self) -> T - where - T: TryFrom, - >::Error: Debug, - { - self.size.try_into().unwrap() - } - pub fn upload_chunk( mut self, http: &ureq::Agent, @@ -135,3 +111,25 @@ impl FileUploading { ChunkState::Ok(self) } } + +impl<'t> SharryFile<'t> for FileUploading { + fn name(&'t self) -> &'t str { + ::extract_file_name(&self.path) + } + + fn offset(&self) -> T + where + T: TryFrom, + >::Error: std::fmt::Debug + std::fmt::Display, + { + ::from_usize(self.offset) + } + + fn size(&self) -> T + where + T: TryFrom, + >::Error: std::fmt::Debug + std::fmt::Display, + { + ::from_usize(self.size) + } +} diff --git a/src/sharry/mod.rs b/src/sharry/mod.rs index 6deb57e..33192d5 100644 --- a/src/sharry/mod.rs +++ b/src/sharry/mod.rs @@ -7,5 +7,5 @@ mod share; pub use alias::Alias; pub use api::{NewShareRequest, Uri}; -pub use file::{ChunkState, FileChecked, FileUploading, UploadError}; +pub use file::{ChunkState, FileChecked, FileUploading, SharryFile, UploadError}; pub use share::Share;