Skip to main content

fileloft_core/
store.rs

1use crate::{
2    error::TusError,
3    info::{UploadId, UploadInfo},
4};
5
6/// Operations on a single upload resource.
7#[trait_variant::make(SendUpload: Send)]
8pub trait Upload {
9    /// Write chunk data starting at `offset`, streaming from `reader`.
10    /// Returns the number of bytes written.
11    async fn write_chunk(
12        &mut self,
13        offset: u64,
14        reader: &mut (dyn tokio::io::AsyncRead + Unpin + Send),
15    ) -> Result<u64, TusError>;
16
17    /// Retrieve current metadata and offset.
18    async fn get_info(&self) -> Result<UploadInfo, TusError>;
19
20    /// Called once all bytes have been received (offset == size).
21    async fn finalize(&mut self) -> Result<(), TusError>;
22
23    /// Delete this upload and free all associated resources.
24    /// Called by the termination extension (DELETE). Return `Err` if unsupported.
25    async fn delete(self) -> Result<(), TusError>;
26
27    /// Set the definitive `Upload-Length` on a deferred-length upload.
28    /// Called when the client provides `Upload-Length` on a PATCH request.
29    async fn declare_length(&mut self, length: u64) -> Result<(), TusError>;
30
31    /// Assemble fully-uploaded partials (in order) into this final upload.
32    /// Called by the concatenation extension.
33    async fn concatenate(&mut self, partials: &[UploadInfo]) -> Result<(), TusError>;
34
35    /// Stream the completed upload bytes for HTTP GET (download) requests.
36    /// Return [`TusError::UploadNotReadyForDownload`] when the upload is incomplete or not readable.
37    async fn read_content(&self) -> Result<Box<dyn tokio::io::AsyncRead + Send + Unpin>, TusError>;
38}
39
40/// Core storage abstraction.
41///
42/// Implement this trait to plug in any persistence backend (filesystem, S3, etc.).
43/// The associated `UploadType` must implement all upload operations; return
44/// `TusError::ExtensionNotEnabled` from extension methods your store doesn't support.
45#[trait_variant::make(SendDataStore: Send)]
46pub trait DataStore {
47    type UploadType: SendUpload;
48
49    /// Create a new upload slot and return a handle to it.
50    async fn create_upload(&self, info: UploadInfo) -> Result<Self::UploadType, TusError>;
51
52    /// Retrieve an existing upload by ID.
53    async fn get_upload(&self, id: &UploadId) -> Result<Self::UploadType, TusError>;
54}