Expand description
§ferro-blob-store
Foundation crate for content-addressed blob storage in the Ferro
ecosystem. A deliberately tiny async fn trait (5 methods) plus
two reference backends (in-memory + filesystem) plus a
Digest newtype with SHA-256 / SHA-512 support.
⚠️ Alpha (
v0.0.1). API may change. The trait surface is minimal on purpose so it stays stable as we add streaming variants inv0.1.
Part of the Ferro ecosystem. Used as the storage abstraction
under ferro-oci-server,
ferro-maven-layout,
and ferro-cargo-registry-server.
§What this crate does
Digest— an<algo>:<hex>content identifier (SHA-256 or SHA-512). Validates hex length and character set on construction. Computes from bytes viaDigest::sha256_of(&[u8]).BlobStore— five-method async trait:put,get,contains,delete,list. Writers verify the SHA-256 of the input matches the supplied digest. Implementations are expected to beSend + Sync.InMemoryBlobStore—Arc<RwLock<HashMap<Digest, Bytes>>>reference implementation. Useful for tests and ephemeral caches.FsBlobStore(default featurefs) — local-filesystem backend that lays out blobs at<root>/<algo>/<2-char-prefix>/<rest-of-hex>. Atomic writes via temp-file + rename.
§What this crate does not do
- Streaming (
put_stream/get_stream). Coming inv0.1. - Cloud backends (S3, GCS, Azure). Use the
object_storecrate family and write a 50-line adapter; the trait is small enough. - Tiered storage (Hot/Warm/Cold). The Ferro internal repo has a router for this; it is not in the public crate.
- Replication / dedupe / compression. Layer it under your own
BlobStoreimpl that wraps an inner one.
§Quick start
use ferro_blob_store::{BlobStore, Digest, InMemoryBlobStore};
use bytes::Bytes;
let store = InMemoryBlobStore::new();
let body = Bytes::from_static(b"hello world");
let digest = Digest::sha256_of(&body);
store.put(&digest, body.clone()).await?;
assert!(store.contains(&digest).await?);
assert_eq!(store.get(&digest).await?, body);
assert_eq!(store.list().await?.len(), 1);Filesystem variant:
use ferro_blob_store::{BlobStore, Digest, FsBlobStore};
use bytes::Bytes;
let store = FsBlobStore::new("/var/lib/my-registry/blobs")?;
let body = Bytes::from_static(b"layer bytes");
let digest = Digest::sha256_of(&body);
store.put(&digest, body).await?;§Status
| Aspect | Status |
|---|---|
| API stability | alpha (v0.0.x) |
| Backends | InMemoryBlobStore ✅ / FsBlobStore ✅ (default feature) |
| Streaming I/O | not yet — v0.1 target |
| MSRV | rustc 1.88 |
| Async runtime | Tokio (for FsBlobStore); the trait itself is runtime-agnostic |
§Used in production by
- ferro-oci-server — OCI Distribution v1.1 server primitives.
- ferro-maven-layout — Maven Repository Layout 2.0 + HTTP handlers.
- ferro-cargo-registry-server — Cargo Alternative Registry sparse-index server.
§License
Apache-2.0. See LICENSE.
Structs§
- Digest
- Content-addressed identifier in
<algo>:<hex>form. - FsBlob
Store fs - Local-filesystem implementation of
BlobStore. - InMemory
Blob Store Arc<RwLock<HashMap<Digest, Bytes>>>reference implementation.
Enums§
- Blob
Store Error - Errors emitted by
crate::BlobStoreimplementations. - Digest
Algo - Hash algorithm used by a
Digest. - Digest
Parse Error - Errors returned when a
<algo>:<hex>string fails validation.
Constants§
- CRATE_
NAME - Crate name, exposed for diagnostics and
/metricslabelling.
Traits§
- Blob
Store - A content-addressed blob store.
Type Aliases§
- Result
- Convenience
Resultalias. - Shared
Blob Store - Convenience type alias:
Arc<dyn BlobStore>.