storage-bindings 0.5.3

Rust bindings for Storage, the Decentralized Durability Engine
use crate::callback::{c_callback, with_libstorage_lock, CallbackFuture};
use crate::error::{Result, StorageError};
use crate::ffi::{storage_list, storage_space};
use crate::node::lifecycle::StorageNode;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Manifest {
    #[serde(skip)]
    pub cid: String,
    #[serde(rename = "treeCid", default)]
    pub tree_cid: String,
    #[serde(rename = "datasetSize")]
    pub dataset_size: usize,
    #[serde(rename = "blockSize")]
    pub block_size: usize,
    #[serde(default)]
    pub filename: String,
    #[serde(default)]
    pub mimetype: String,
    #[serde(default)]
    pub protected: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestWithCid {
    pub cid: String,
    pub manifest: Manifest,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Space {
    #[serde(rename = "totalBlocks")]
    pub total_blocks: usize,
    #[serde(rename = "quotaMaxBytes")]
    pub quota_max_bytes: u64,
    #[serde(rename = "quotaUsedBytes")]
    pub quota_used_bytes: u64,
    #[serde(rename = "quotaReservedBytes")]
    pub quota_reserved_bytes: u64,
}

pub async fn manifests(node: &StorageNode) -> Result<Vec<Manifest>> {
    let future = CallbackFuture::new();
    let context_ptr = future.context_ptr();

    let result = with_libstorage_lock(|| unsafe {
        node.with_ctx(|ctx| storage_list(ctx as *mut _, Some(c_callback), context_ptr.as_ptr()))
    });

    if result != 0 {
        return Err(StorageError::storage_operation_error(
            "manifests",
            "Failed to list manifests",
        ));
    }

    let manifests_json = future.await?;

    let manifests_with_cid: Vec<ManifestWithCid> = serde_json::from_str(&manifests_json)
        .map_err(|e| StorageError::library_error(format!("Failed to parse manifests: {}", e)))?;

    let manifests: Vec<Manifest> = manifests_with_cid
        .into_iter()
        .map(|item| {
            let mut manifest = item.manifest;
            manifest.cid = item.cid;
            manifest
        })
        .collect();

    Ok(manifests)
}

pub async fn space(node: &StorageNode) -> Result<Space> {
    let future = CallbackFuture::new();
    let context_ptr = future.context_ptr();

    let result = with_libstorage_lock(|| unsafe {
        node.with_ctx(|ctx| storage_space(ctx as *mut _, Some(c_callback), context_ptr.as_ptr()))
    });

    if result != 0 {
        return Err(StorageError::storage_operation_error(
            "space",
            "Failed to get storage space",
        ));
    }

    let space_json = future.await?;

    let space: Space = serde_json::from_str(&space_json)
        .map_err(|e| StorageError::library_error(format!("Failed to parse space info: {}", e)))?;

    Ok(space)
}