Skip to main content

Crate ferro_blob_store

Crate ferro_blob_store 

Source
Expand description

§ferro-blob-store

License Rust 1.88+

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 in v0.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 via Digest::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 be Send + Sync.
  • InMemoryBlobStoreArc<RwLock<HashMap<Digest, Bytes>>> reference implementation. Useful for tests and ephemeral caches.
  • FsBlobStore (default feature fs) — 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 in v0.1.
  • Cloud backends (S3, GCS, Azure). Use the object_store crate 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 BlobStore impl 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

AspectStatus
API stabilityalpha (v0.0.x)
BackendsInMemoryBlobStore ✅ / FsBlobStore ✅ (default feature)
Streaming I/Onot yet — v0.1 target
MSRVrustc 1.88
Async runtimeTokio (for FsBlobStore); the trait itself is runtime-agnostic

§Used in production by

§License

Apache-2.0. See LICENSE.

Structs§

Digest
Content-addressed identifier in <algo>:<hex> form.
FsBlobStorefs
Local-filesystem implementation of BlobStore.
InMemoryBlobStore
Arc<RwLock<HashMap<Digest, Bytes>>> reference implementation.

Enums§

BlobStoreError
Errors emitted by crate::BlobStore implementations.
DigestAlgo
Hash algorithm used by a Digest.
DigestParseError
Errors returned when a <algo>:<hex> string fails validation.

Constants§

CRATE_NAME
Crate name, exposed for diagnostics and /metrics labelling.

Traits§

BlobStore
A content-addressed blob store.

Type Aliases§

Result
Convenience Result alias.
SharedBlobStore
Convenience type alias: Arc<dyn BlobStore>.