implement SharryFile trait
This commit is contained in:
parent
39560eeeed
commit
e98001f4a4
6 changed files with 111 additions and 42 deletions
|
|
@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
cli::Cli,
|
cli::Cli,
|
||||||
sharry::{Alias, ChunkState, FileChecked, FileUploading, Share, UploadError},
|
sharry::{Alias, ChunkState, FileChecked, FileUploading, Share, SharryFile, UploadError},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
@ -37,8 +37,8 @@ enum FileState {
|
||||||
impl FileState {
|
impl FileState {
|
||||||
fn file_name(&self) -> &str {
|
fn file_name(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
FileState::C(checked) => checked.file_name(),
|
FileState::C(checked) => checked.name(),
|
||||||
FileState::U(uploading) => uploading.file_name(),
|
FileState::U(uploading) => uploading.name(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +145,7 @@ impl AppState {
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.with_message(uploading.file_name().to_owned())
|
.with_message(uploading.name().to_owned())
|
||||||
.with_position(uploading.offset());
|
.with_position(uploading.offset());
|
||||||
|
|
||||||
bar.enable_steady_tick(Duration::from_millis(100));
|
bar.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use log::debug;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ureq::http::StatusCode;
|
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)]
|
#[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct FileChecked {
|
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(
|
pub fn start_upload(
|
||||||
self,
|
self,
|
||||||
http: &ureq::Agent,
|
http: &ureq::Agent,
|
||||||
alias: &Alias,
|
alias: &Alias,
|
||||||
share: &Share,
|
share: &Share,
|
||||||
) -> io::Result<FileUploading> {
|
) -> io::Result<FileUploading> {
|
||||||
let size = usize::try_from(fs::metadata(&self.path)?.len()).map_err(io::Error::other)?;
|
let size: usize = self.size();
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let endpoint = alias.get_endpoint(format!("alias/upload/{}/files/tus", share.id));
|
let endpoint = alias.get_endpoint(format!("alias/upload/{}/files/tus", share.id));
|
||||||
|
|
||||||
(http.post(endpoint))
|
(http.post(endpoint))
|
||||||
.sharry_header(alias)
|
.sharry_header(alias)
|
||||||
.header("Sharry-File-Name", self.file_name())
|
.header("Sharry-File-Name", self.name())
|
||||||
.header("Upload-Length", size)
|
.header("Upload-Length", size)
|
||||||
.send_empty()
|
.send_empty()
|
||||||
.map_err(io::Error::other)?
|
.map_err(ureq::Error::into_io)?
|
||||||
};
|
};
|
||||||
|
|
||||||
if res.status() != StatusCode::CREATED {
|
if res.status() != StatusCode::CREATED {
|
||||||
|
|
@ -71,3 +64,29 @@ impl FileChecked {
|
||||||
Ok(FileUploading::new(self.path, size, location))
|
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 {
|
||||||
|
<Self as SharryFile>::extract_file_name(&self.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: std::fmt::Debug + std::fmt::Display,
|
||||||
|
{
|
||||||
|
<Self as SharryFile>::from_usize(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: std::fmt::Debug + std::fmt::Display,
|
||||||
|
{
|
||||||
|
let val = <Self as SharryFile>::to_usize(fs::metadata(&self.path).unwrap().len());
|
||||||
|
<Self as SharryFile>::from_usize(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
50
src/sharry/file/filetrait.rs
Normal file
50
src/sharry/file/filetrait.rs
Normal file
|
|
@ -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<T>(val: usize) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: Debug + Display,
|
||||||
|
{
|
||||||
|
val.try_into()
|
||||||
|
.inspect_err(|e| panic!("usize did not fit into other type: {e}"))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_usize<T>(val: T) -> usize
|
||||||
|
where
|
||||||
|
T: TryInto<usize>,
|
||||||
|
<T as TryInto<usize>>::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<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: Debug + Display;
|
||||||
|
|
||||||
|
fn size<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: Debug + Display;
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
mod checked;
|
mod checked;
|
||||||
|
mod filetrait;
|
||||||
mod uploading;
|
mod uploading;
|
||||||
|
|
||||||
pub use checked::FileChecked;
|
pub use checked::FileChecked;
|
||||||
|
pub use filetrait::SharryFile;
|
||||||
pub use uploading::{ChunkState, FileUploading, UploadError};
|
pub use uploading::{ChunkState, FileUploading, UploadError};
|
||||||
|
|
||||||
use super::{Alias, Share, alias::SharryAlias};
|
use super::{Alias, Share, alias::SharryAlias};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fmt::{Debug, Display},
|
|
||||||
fs,
|
fs,
|
||||||
io::{self, Read, Seek, SeekFrom},
|
io::{self, Read, Seek, SeekFrom},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
|
@ -10,7 +9,7 @@ use log::debug;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use ureq::http::{HeaderValue, StatusCode};
|
use ureq::http::{HeaderValue, StatusCode};
|
||||||
|
|
||||||
use super::{Alias, SharryAlias};
|
use super::{Alias, SharryAlias, SharryFile};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct FileUploading {
|
pub struct FileUploading {
|
||||||
|
|
@ -34,7 +33,7 @@ pub enum ChunkState {
|
||||||
Finished(PathBuf),
|
Finished(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FileUploading {
|
impl std::fmt::Display for FileUploading {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
|
@ -69,29 +68,6 @@ impl FileUploading {
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_name(&self) -> &str {
|
|
||||||
self.path
|
|
||||||
.file_name()
|
|
||||||
.and_then(OsStr::to_str)
|
|
||||||
.expect("bad file name")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn offset<T>(&self) -> T
|
|
||||||
where
|
|
||||||
T: TryFrom<usize>,
|
|
||||||
<T as TryFrom<usize>>::Error: Debug,
|
|
||||||
{
|
|
||||||
self.offset.try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size<T>(&self) -> T
|
|
||||||
where
|
|
||||||
T: TryFrom<usize>,
|
|
||||||
<T as TryFrom<usize>>::Error: Debug,
|
|
||||||
{
|
|
||||||
self.size.try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn upload_chunk(
|
pub fn upload_chunk(
|
||||||
mut self,
|
mut self,
|
||||||
http: &ureq::Agent,
|
http: &ureq::Agent,
|
||||||
|
|
@ -135,3 +111,25 @@ impl FileUploading {
|
||||||
ChunkState::Ok(self)
|
ChunkState::Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'t> SharryFile<'t> for FileUploading {
|
||||||
|
fn name(&'t self) -> &'t str {
|
||||||
|
<Self as SharryFile>::extract_file_name(&self.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: std::fmt::Debug + std::fmt::Display,
|
||||||
|
{
|
||||||
|
<Self as SharryFile>::from_usize(self.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size<T>(&self) -> T
|
||||||
|
where
|
||||||
|
T: TryFrom<usize>,
|
||||||
|
<T as TryFrom<usize>>::Error: std::fmt::Debug + std::fmt::Display,
|
||||||
|
{
|
||||||
|
<Self as SharryFile>::from_usize(self.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,5 @@ mod share;
|
||||||
|
|
||||||
pub use alias::Alias;
|
pub use alias::Alias;
|
||||||
pub use api::{NewShareRequest, Uri};
|
pub use api::{NewShareRequest, Uri};
|
||||||
pub use file::{ChunkState, FileChecked, FileUploading, UploadError};
|
pub use file::{ChunkState, FileChecked, FileUploading, SharryFile, UploadError};
|
||||||
pub use share::Share;
|
pub use share::Share;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue