| Crates.io | helia-mfs |
| lib.rs | helia-mfs |
| version | 0.1.3 |
| created_at | 2025-10-11 04:11:02.67639+00 |
| updated_at | 2025-10-11 04:11:02.67639+00 |
| description | Mutable File System (MFS) implementation for Helia IPFS nodes |
| homepage | https://github.com/cyberfly-io/rust-helia |
| repository | https://github.com/cyberfly-io/rust-helia |
| max_upload_size | |
| id | 1877845 |
| size | 186,975 |
A Rust implementation of the Mutable File System (MFS) for IPFS/Helia.
MFS (Mutable File System) provides a familiar filesystem-like interface over IPFS's immutable content-addressed storage. It maintains a mutable root pointer that allows you to modify your filesystem while still benefiting from IPFS's content addressing and deduplication.
Think of MFS as your "working directory" in IPFS - you can create, modify, and delete files and directories as you would with a traditional filesystem, while under the hood everything is still content-addressed and immutable.
/path/to/file style pathsAdd this to your Cargo.toml:
[dependencies]
helia-mfs = "0.1.0"
use helia_mfs::{mfs, MfsInterface};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let helia = helia::create_helia_default().await?;
let fs = mfs(Arc::new(helia));
// Create a directory
fs.mkdir("/my-directory").await?;
// Write a file
let data = b"Hello, MFS!";
fs.write_bytes(data, "/my-directory/hello.txt").await?;
// List directory contents
let entries = fs.ls(Some("/")).await?;
for entry in entries {
println!("Entry: {}", entry.name);
}
Ok(())
}
// Create a directory at root
fs.mkdir("/documents").await?;
// Create nested directories (parent must exist first)
fs.mkdir("/documents/2024").await?;
// Write text data
let text = b"This is a test document";
fs.write_bytes(text, "/documents/test.txt").await?;
// Write binary data
let binary_data = vec![0x00, 0x01, 0x02, 0x03];
fs.write_bytes(&binary_data, "/documents/data.bin").await?;
// List root directory
let entries = fs.ls(None).await?;
for entry in entries {
println!("{} - Type: {:?}", entry.name, entry.type_);
}
// List specific directory
let entries = fs.ls(Some("/documents")).await?;
for entry in entries {
println!("{} - CID: {}", entry.name, entry.cid);
}
MFS maintains a mutable root CID that gets updated whenever you make changes to the filesystem. Each operation:
This approach provides:
MFS (Mutable Layer)
↓
UnixFS (Filesystem Layer)
↓
Helia (IPFS Core)
↓
Blockstore (Storage Layer)
pub trait MfsInterface: Send + Sync {
/// Create a directory at the given path
async fn mkdir(&self, path: &str) -> Result<(), MfsError>;
/// Write bytes to a file at the given path
async fn write_bytes(&self, bytes: &[u8], path: &str) -> Result<(), MfsError>;
/// List entries in a directory (None for root)
async fn ls(&self, path: Option<&str>) -> Result<Vec<UnixFSEntry>, MfsError>;
}
All paths must:
/ (absolute paths)/ as the path separatorExamples:
/file.txt/documents/report.pdf/data/2024/january/metrics.jsonfile.txt (no leading slash)/ (cannot write to root)pub enum MfsError {
InvalidPath(String), // Path format errors
UnixFs(String), // Underlying UnixFS errors
}
✅ Implemented:
⚠️ Limitations:
🔄 Future Enhancements:
mkdir -p equivalent)| Feature | This Implementation | JS Helia |
|---|---|---|
| Basic operations | ✅ mkdir, write, ls | ✅ Full API |
| Path resolution | ⚠️ Simplified | ✅ Complete |
| Nested paths | ❌ Single level | ✅ Full support |
| File operations | ⚠️ Write only | ✅ Read/write |
| Root management | ✅ Automatic | ✅ Configurable |
use helia_mfs::{mfs, MfsInterface};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize Helia and MFS
let helia = helia::create_helia_default().await?;
let fs = mfs(Arc::new(helia));
// Create directory structure
fs.mkdir("/projects").await?;
fs.mkdir("/documents").await?;
// Write project file
let code = b"fn main() { println!(\"Hello!\"); }";
fs.write_bytes(code, "/projects/main.rs").await?;
// Write documentation
let docs = b"# Project Documentation\n\nThis is my project.";
fs.write_bytes(docs, "/documents/README.md").await?;
// List all files
println!("Root contents:");
for entry in fs.ls(None).await? {
println!(" - {} ({:?})", entry.name, entry.type_);
}
Ok(())
}
Run the test suite:
cargo test
Current tests:
test_mkdir: Verify directory creationtest_write_bytes: Verify file writingtest_ls_root: Verify directory listingContributions are welcome! Areas for improvement:
Licensed under either of
at your option.