shrupl/src/file/uploading.rs

115 lines
2.5 KiB
Rust
Raw Normal View History

use std::{
fs,
io::{self, Read, Seek, SeekFrom},
path::PathBuf,
};
use log::warn;
use serde::{Deserialize, Serialize};
use crate::sharry;
2025-06-25 23:15:33 +00:00
2025-06-18 19:40:34 +00:00
use super::{Checked, Chunk, FileTrait};
#[derive(Serialize, Deserialize, Debug)]
pub struct Uploading {
/// canonical path to a regular file
2025-06-04 16:58:18 +00:00
path: PathBuf,
/// size of that file
2025-06-06 23:42:18 +00:00
size: u64,
/// hash of that file
hash: Option<String>,
2025-06-25 23:15:33 +00:00
file_id: sharry::FileID,
#[serde(skip)]
last_offset: Option<u64>,
2025-06-06 23:42:18 +00:00
offset: u64,
}
impl Uploading {
2025-06-25 23:15:33 +00:00
pub(super) fn new(
path: PathBuf,
size: u64,
hash: Option<String>,
file_id: sharry::FileID,
) -> Self {
2025-06-04 16:58:18 +00:00
Self {
path,
size,
hash,
file_id,
last_offset: None,
2025-06-04 16:58:18 +00:00
offset: 0,
}
}
2025-06-06 23:42:18 +00:00
pub fn get_offset(&self) -> u64 {
self.offset
}
pub fn rewind(mut self) -> Option<Self> {
if let Some(last_offset) = self.last_offset {
self.last_offset = None;
self.offset = last_offset;
Some(self)
} else {
2025-06-13 23:11:40 +00:00
warn!("attempted to rewind twice");
None
}
}
pub fn read<'t>(&mut self, buf: &'t mut [u8]) -> io::Result<Chunk<'t>> {
2025-06-05 22:08:24 +00:00
let mut f = fs::File::open(&self.path)?;
f.seek(SeekFrom::Start(self.offset))?;
let read_len = f.read(buf)?;
if read_len == 0 {
return Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
format!("could not read from file {:?}", self.path.display()),
));
}
let chunk = Chunk::new(self.file_id.clone(), self.offset, &buf[..read_len]);
self.last_offset = Some(self.offset);
self.offset += chunk.get_length();
Ok(chunk)
}
pub fn check_eof(self) -> Result<Self, PathBuf> {
if self.offset < self.size {
Ok(self)
} else {
Err(self.path)
}
}
2025-06-18 19:40:34 +00:00
pub fn abort(self) -> Checked {
Checked {
path: self.path,
size: self.size,
hash: self.hash,
2025-06-18 19:40:34 +00:00
}
}
}
2025-06-06 15:21:49 +00:00
impl<'t> FileTrait<'t> for Uploading {
2025-06-06 23:42:18 +00:00
fn get_name(&'t self) -> &'t str {
<Self as FileTrait>::extract_file_name(&self.path)
2025-06-06 15:21:49 +00:00
}
2025-06-06 23:42:18 +00:00
fn get_size(&self) -> u64 {
self.size
2025-06-06 15:21:49 +00:00
}
2025-07-03 18:27:41 +00:00
fn check_hash(&self, on_progress: impl FnMut(u64)) -> crate::Result<()> {
super::check_hash(
&self.path,
self.size,
self.hash.as_ref().map(String::as_str),
on_progress,
)
}
2025-06-06 15:21:49 +00:00
}