use std::{ fs, io, path::{Path, PathBuf}, }; use serde::{Deserialize, Serialize}; use crate::sharry; use super::{FileTrait, Uploading}; /// Description of an existing, regular file /// /// - impl Debug, Clone, Hash for `clap` compatibility /// - impl serde for appstate caching /// - impl Ord to handle multiple files given #[derive(Debug, Clone, Hash, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Checked { /// canonical path to a regular file path: PathBuf, /// size of that file size: u64, } impl Checked { /// create a new checked file from some path reference /// /// # Errors /// /// - from `fs::metadata(path)` or `fs::canonicalize` /// - given path does not correspond to a regular file pub fn new(value: impl AsRef) -> io::Result { let meta = fs::metadata(&value)?; if meta.is_file() { Ok(Self { path: fs::canonicalize(&value)?, size: meta.len(), }) } else { Err(io::Error::new( io::ErrorKind::InvalidInput, "Not a regular file", )) } } /// start uploading this file /// /// - tries to create a new entry in a share /// - expects endpoint like `{base_uri}/alias/upload/{share_id}/files/tus` /// - consumes `self` into a `file::Uploading` struct /// /// # Errors /// /// TODO documentation after `ClientError` rework pub fn start_upload( self, client: &impl sharry::Client, endpoint: &str, alias_id: &str, ) -> sharry::Result { let patch_uri = client.file_create(endpoint, alias_id, self.get_name(), self.size)?; Ok(Uploading::new(self.path, self.size, patch_uri)) } } impl<'t> FileTrait<'t> for Checked { /// get a reference to the file's name /// /// Uses `SharryFile::extract_file_name`, which may **panic**! fn get_name(&'t self) -> &'t str { ::extract_file_name(&self.path) } /// get the file's size fn get_size(&self) -> u64 { self.size } }