Crate helia_mfs

Crate helia_mfs 

Source
Expand description

Mutable File System (MFS) for Helia

This module provides a mutable file system layer on top of UnixFS, allowing users to work with IPFS content using familiar file system operations.

§Overview

MFS (Mutable File System) provides a POSIX-like interface for interacting with IPFS content. While IPFS content is inherently immutable, MFS maintains a mutable “view” into the content-addressed data by tracking the root CID of your file system tree and updating it as you make changes.

§Core Concepts

  • Immutable Content: All UnixFS content is stored immutably using content-addressed CIDs. When you modify a file, a new CID is created.
  • Mutable Root: MFS tracks a single “root” CID that represents your current file system state. This root is updated after each modification.
  • Directory Chains: Modifying any file requires updating its parent directory, which requires updating that directory’s parent, all the way to the root.

§Supported Operations

  • mkdir - Create directories (like mkdir -p)
  • write_bytes - Write files from byte slices
  • ls - List directory contents
  • stat - Get file/directory metadata
  • cp - Copy files or directories
  • mv - Move/rename files or directories
  • rm - Remove files or directories
  • root_cid - Get the current root CID
  • flush - Ensure changes are persisted

§Example Usage

use helia_mfs::{mfs, MfsInterface};
use rust_helia::create_helia_default;
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a Helia node
    let helia = Arc::new(create_helia_default().await?);
     
    // Create an MFS instance
    let fs = mfs(helia);
     
    // Create a directory
    fs.mkdir("/documents").await?;
     
    // Write a file
    fs.write_bytes("/documents/hello.txt", b"Hello, IPFS!").await?;
     
    // List contents
    let entries = fs.ls("/documents").await?;
    for entry in entries {
        println!("{}: {} bytes", entry.name, entry.size);
    }
     
    // Copy a file
    fs.cp("/documents/hello.txt", "/documents/hello_copy.txt").await?;
     
    // Move a file
    fs.mv("/documents/hello_copy.txt", "/backup.txt").await?;
     
    // Remove a file
    fs.rm("/backup.txt", false).await?;
     
    // Get the root CID (represents your entire file system)
    if let Some(root) = fs.root_cid().await {
        println!("File system root: {}", root);
    }
     
    Ok(())
}

§Performance Considerations

  • Copy Operations: Copying files is O(1) in space - only directory metadata is copied, not the actual file content.
  • Deep Paths: Operations on deeply nested paths require updating the entire directory chain from the modified file up to the root.
  • Large Directories: Listing and modifying large directories may be slow as all entries must be loaded into memory.

§Thread Safety

All MFS operations are thread-safe and can be called concurrently from multiple tasks. The root CID is protected by an RwLock to ensure consistency.

§Error Handling

Operations return Result<T, MfsError> where MfsError provides detailed information about what went wrong. Common errors include:

  • InvalidPath - Malformed or invalid paths
  • NotFound - File or directory doesn’t exist
  • UnixFs - Underlying UnixFS operation failed

§Limitations

  • No Metadata Updates: Operations like touch() (update timestamps) and chmod() (change permissions) would require recreating content with new metadata, which is not yet implemented.
  • No Streaming: Large files must fit in memory during write operations.
  • No Transactions: Operations are not transactional beyond atomic mv().

Structs§

DefaultMfs
Default MFS implementation
MfsPath
Represents a parsed MFS path

Enums§

MfsError
Error types for MFS operations

Traits§

MfsInterface
Trait defining the MFS interface

Functions§

mfs
Create an MFS instance