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}