[wip] documentation for file module

This commit is contained in:
Jörn-Michael Miehe 2025-07-03 18:27:41 +00:00
parent 61d62d731e
commit 5a34a8d791
3 changed files with 55 additions and 18 deletions

View file

@ -54,6 +54,12 @@ impl Checked {
}
}
/// calculate and store hash for this file
///
/// # Errors
///
/// - from `file::compute_hash`
/// - Mismatch if file already hashed
pub fn hash(&mut self, f: impl Fn(u64)) -> crate::Result<()> {
if self.hash.is_some() {
return Err(crate::Error::mismatch("unhashed file", self.path.display()));
@ -64,15 +70,14 @@ impl Checked {
Ok(())
}
/// start uploading this file
/// starts uploading this file
///
/// - tries to create a new entry in a share
/// - expects endpoint like `{base_uri}/alias/upload/{share_id}/files/tus`
/// - tries to create a new file using the client
/// - consumes `self` into a `file::Uploading` struct
///
/// # Errors
///
/// TODO documentation after `ClientError` rework
/// - from `sharry::Client::file_create`
pub fn start_upload(
self,
client: &impl sharry::Client,
@ -87,19 +92,15 @@ impl Checked {
}
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 {
<Self as FileTrait>::extract_file_name(&self.path)
}
/// get the file's size
fn get_size(&self) -> u64 {
self.size
}
fn check_hash(&self, on_progress: impl Fn(u64)) -> crate::Result<()> {
fn check_hash(&self, on_progress: impl FnMut(u64)) -> crate::Result<()> {
super::check_hash(
&self.path,
self.size,

View file

@ -12,22 +12,38 @@ pub use chunk::Chunk;
use log::{debug, warn};
pub use uploading::Uploading;
/// how many bytes to hash at once (default: 4 MiB)
const HASH_CHUNK_SIZE: usize = 4 * 1024 * 1024;
/// compute hash for a file given its path.
/// Hash function: BLAKE2b, 512 bit
///
/// # Params
///
/// - `path` to the file to hash
/// - `size` of that file
/// - `on_progress` will be called for each processed chunk (max. `HASH_CHUNK_SIZE`)
///
/// # Errors
///
/// - from `fs::File::open` and `fs::File::read`
/// - Mismatch if given `size` does not match the file's size
fn compute_hash(path: &Path, size: u64, mut on_progress: impl FnMut(u64)) -> crate::Result<String> {
let mut file = fs::File::open(path)?;
// Blake2b-512 hasher (64 * 8 bit)
let mut hasher = Blake2b::new().hash_length(64).to_state();
// buffer (4 MiB)
let mut buf = vec![0; 4 * 1024 * 1024];
// buffer
let mut buffer = vec![0; HASH_CHUNK_SIZE];
let mut bytes_read = 0;
loop {
let n = file.read(&mut buf)?;
let n = file.read(&mut buffer)?;
if n == 0 {
break;
}
hasher.update(&buf[..n]);
hasher.update(&buffer[..n]);
// `buf` size must be < 2 EiB
bytes_read += n as u64;
@ -43,16 +59,32 @@ fn compute_hash(path: &Path, size: u64, mut on_progress: impl FnMut(u64)) -> cra
Ok(result)
}
/// check hash for a file given its path, return Ok(()) on success
///
/// # Params
///
/// - `path` to the file to hash
/// - `size` of that file
/// - optional known `hash`
/// - `on_progress` will be called for each processed chunk (max. `HASH_CHUNK_SIZE`)
///
/// # Errors
///
/// - from `file::compute_hash`
/// - Mismatch if `hash` is `None`
/// - Mismatch if given `hash` does not match the computed hash
fn check_hash(
path: &Path,
size: u64,
hash: Option<&str>,
on_progress: impl FnMut(u64),
) -> crate::Result<()> {
// check if hash is None
let Some(expected) = hash else {
return Err(crate::Error::mismatch("hash", path.display()));
};
// compute and check new hash
let actual = &compute_hash(path, size, on_progress)?;
if expected == actual {
@ -77,12 +109,19 @@ pub trait FileTrait<'t> {
}
/// get a reference to the file's name
///
/// Uses `file::FileTrait::extract_file_name`, which may **panic**!
fn get_name(&'t self) -> &'t str;
/// get the file's size
fn get_size(&self) -> u64;
fn check_hash(&self, on_progress: impl Fn(u64)) -> crate::Result<()>;
/// check this file's hash, return Ok(()) on success
///
/// # Errors
///
/// - from `file::check_hash`
fn check_hash(&self, on_progress: impl FnMut(u64)) -> crate::Result<()>;
}
#[cfg(test)]

View file

@ -95,9 +95,6 @@ impl Uploading {
}
impl<'t> FileTrait<'t> for Uploading {
/// get a reference to the file's name
///
/// Uses `SharryFile::extract_file_name`, which may **panic**!
fn get_name(&'t self) -> &'t str {
<Self as FileTrait>::extract_file_name(&self.path)
}
@ -106,7 +103,7 @@ impl<'t> FileTrait<'t> for Uploading {
self.size
}
fn check_hash(&self, on_progress: impl Fn(u64)) -> crate::Result<()> {
fn check_hash(&self, on_progress: impl FnMut(u64)) -> crate::Result<()> {
super::check_hash(
&self.path,
self.size,