use crate::callback::{c_callback, with_libstorage_lock, CallbackFuture};
use crate::error::{Result, StorageError};
use crate::ffi::{
free_c_string, storage_upload_cancel, storage_upload_finalize, storage_upload_init,
string_to_c_string,
};
use crate::node::lifecycle::StorageNode;
use crate::upload::types::UploadOptions;
use libc::c_void;
pub async fn upload_init(node: &StorageNode, options: &UploadOptions) -> Result<String> {
options.validate()?;
let future = CallbackFuture::new();
let filepath_str = options
.filepath
.as_ref()
.and_then(|p| p.to_str())
.unwrap_or("");
let chunk_size = options.chunk_size.unwrap_or(1024 * 1024);
let context_ptr = future.context_ptr() as *mut c_void;
let result = with_libstorage_lock(|| unsafe {
node.with_ctx(|ctx| {
let c_filepath = string_to_c_string(filepath_str);
let result = storage_upload_init(
ctx as *mut _,
c_filepath,
chunk_size,
Some(c_callback),
context_ptr,
);
if !c_filepath.is_null() {
free_c_string(c_filepath);
}
result
})
});
if result != 0 {
return Err(StorageError::upload_error("Failed to initialize upload"));
}
let session_id = future.await?;
Ok(session_id)
}
pub async fn upload_finalize(node: &StorageNode, session_id: &str) -> Result<String> {
if session_id.is_empty() {
return Err(StorageError::invalid_parameter(
"session_id",
"Session ID cannot be empty",
));
}
let future = CallbackFuture::new();
let context_ptr = future.context_ptr() as *mut c_void;
let result = with_libstorage_lock(|| unsafe {
node.with_ctx(|ctx| {
let c_session_id = string_to_c_string(session_id);
let result =
storage_upload_finalize(ctx as *mut _, c_session_id, Some(c_callback), context_ptr);
free_c_string(c_session_id);
result
})
});
if result != 0 {
return Err(StorageError::upload_error("Failed to finalize upload"));
}
let cid = future.await?;
Ok(cid)
}
pub async fn upload_cancel(node: &StorageNode, session_id: &str) -> Result<()> {
if session_id.is_empty() {
return Err(StorageError::invalid_parameter(
"session_id",
"Session ID cannot be empty",
));
}
let future = CallbackFuture::new();
let context_ptr = future.context_ptr() as *mut c_void;
let result = with_libstorage_lock(|| unsafe {
node.with_ctx(|ctx| {
let c_session_id = string_to_c_string(session_id);
let result =
storage_upload_cancel(ctx as *mut _, c_session_id, Some(c_callback), context_ptr);
free_c_string(c_session_id);
result
})
});
if result != 0 {
return Err(StorageError::upload_error("Failed to cancel upload"));
}
future.await?;
Ok(())
}