libvctrl_core
Version: 2.0.1
Crate type: Rust library (reference implementations)
Workspace: libvcrtl
libvctrl_core is the batteries-included reference implementation layer for the abstract contracts defined in libvctrl_handler. It provides production-ready, safe implementations of hashing, binary serialization, in-memory storage, reference management, and builder utilities. By consuming libvctrl_handler as its first downstream crate, libvctrl_core validates the contracts and gives developers a complete, working VCS backend stack out of the box.
The crate enforces the same strict code quality standards as libvctrl_handler:
#![forbid(unsafe_code)]#![deny(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]#![deny(missing_docs)]#![deny(rust_2018_idioms, unreachable_pub, unused_crate_dependencies, unused_qualifications)]
Table of Contents
- Overview
- System Architecture
- Core Features
- Technology Stack
- Project Structure
- Getting Started
- Usage
- API Reference
- Testing
- CI/CD Pipeline
- Deployment / Distribution
- Security & Compliance
- Contributing
- License
- Changelog
Overview
libvctrl_core is the first concrete consumer of the libvctrl_handler traits. It transforms the abstract contracts into a runnable foundation for version control systems by providing:
- Binary codec for deterministic serialization and deserialization.
- SHA-512 hasher for content addressing.
- In-memory object and reference stores for ephemeral storage.
- Builder patterns for ergonomic object construction.
- Validation utilities for names and hashes.
Because libvctrl_core implements every key trait from libvctrl_handler, it also serves as a quality exemplar for downstream developers who need to write custom backends. All code is safe, strictly linted, heavily documented, and thoroughly tested.
This crate intentionally does not perform persistent disk I/O or network operations; it focuses on core VCS logic that can be embedded in larger systems.
System Architecture
Workspace Context
Within the libvcrtl workspace, libvctrl_core sits directly above libvctrl_handler and below higher-level crates like libvctrl_plumbing and libvctrl_porcelain.
graph TD
HANDLER[libvctrl_handler<br/>Contracts and Types]
CORE[libvctrl_core<br/>Reference Implementations]
PLUMBING[libvctrl_plumbing]
PORCELAIN[libvctrl_porcelain]
SHA512[libvctrl_sha512<br/>Hash Implementation]
LIBVCTRL[libvctrl CLI]
HANDLER --> CORE
SHA512 --> CORE
CORE --> PLUMBING
CORE --> PORCELAIN
PLUMBING --> LIBVCTRL
PORCELAIN --> LIBVCTRL
libvctrl_core depends on:
libvctrl_handlerversion 4.4.0 for all contracts and data types.libvctrl_sha512version 2.0.0 for the raw SHA-512 hash algorithm.
Internal Module Architecture
The crate is organized by domain responsibility:
graph LR
ROOT[libvctrl_core]
CODEC[codec]
HASH[hash]
OBJECT[object]
STORE[store]
VALIDATE[validate]
ROOT --> CODEC
ROOT --> HASH
ROOT --> OBJECT
ROOT --> STORE
ROOT --> VALIDATE
CODEC --> HANDLER[libvctrl_handler]
HASH --> HANDLER
HASH --> SHA[libvctrl_sha512]
OBJECT --> HANDLER
STORE --> HANDLER
VALIDATE --> HANDLER
Each module isolates a single responsibility:
codec:BinaryEncoderandBinaryDecoderfor binary serialization.hash:Sha512Hasherbridginglibvctrl_sha512toHasher.object: Builder structs for ergonomic construction.store: In-memoryObjectStoreandRefStoreimplementations.validate: Validation helpers for names and hashes.
Object Lifecycle Data Flow
The following sequence shows how a Blob is encoded, hashed, stored, and retrieved using libvctrl_core.
sequenceDiagram
participant App as Downstream App
participant Enc as BinaryEncoder
participant Hash as Sha512Hasher
participant Store as MemoryStore
App->>Enc: encode_blob(&blob)
Enc-->>App: Vec<u8>
App->>Hash: hash(&encoded_bytes)
Hash-->>App: Hash
App->>Store: put(&hash, &encoded_bytes)
App->>Store: get(&hash)
Store-->>App: Box<dyn Read>
Core Features
-
Binary serialization/deserialization
Compact, deterministic, little-endian binary format with versioning and strict bounds checks. -
SHA-512 content addressing
Produces 64-byte digests matchingHASH_LENGTH, using an audited pure-Rust backend. -
Streaming object reads
MemoryStore::getreturnsBox<dyn Read>, enabling incremental consumption without large contiguous allocations. -
In-memory reference store
MemoryRefStoresupports branch and tag management with deterministic sorted iteration. -
Ergonomic builder patterns
Fluent APIs for constructing blobs, commits, tags, trees, and tree entries. -
Defensive validation
Prevents path traversal, empty names, and invalid hash lengths. -
Full POSIX tree fidelity
Encoder and decoder support all fiveEntryKindvariants:Blob,Executable,Symlink,Tree,Submodule. -
Thread-safe and allocation-efficient
All concrete types areSend + Sync; builders transfer ownership without cloning.
Technology Stack
- Language: Rust (edition 2024)
- Dependencies:
libvctrl_handler4.4.0 — contracts and typeslibvctrl_sha5122.0.0 — SHA-512 implementation
- Dev dependencies:
proptest1.11.0 — property-based testing
- Standard library:
std::collections::HashMapstd::io::{Cursor, Read}std::str
- Lints: Clippy all, pedantic, nursery, cargo (all denied)
Project Structure
Within the libvctrl_core crate:
libvctrl_core/
├── Cargo.toml
└── src/
├── lib.rs
├── codec/
│ ├── mod.rs
│ ├── binary_encoder.rs
│ └── binary_decoder.rs
├── hash/
│ ├── mod.rs
│ └── sha512.rs
├── object/
│ ├── mod.rs
│ ├── blob.rs
│ ├── commit.rs
│ ├── tag.rs
│ └── tree.rs
├── store/
│ ├── mod.rs
│ ├── memory.rs
│ └── ref_store.rs
└── validate/
├── mod.rs
├── hash.rs
└── name.rs
Getting Started
Prerequisites
- Rust toolchain 1.96.0 or newer (edition 2024 required)
- Cargo
- No external services or system dependencies
Installation
Add libvctrl_core to your Cargo.toml:
[]
= "2.0.1"
Or use Cargo:
This will automatically pull the required libvctrl_handler and libvctrl_sha512 dependencies.
Configuration
No configuration is required. The crate is a pure library with no environment variables or runtime configuration.
Usage
Quick Start: Encode, Hash, Store, Retrieve
use ;
use BinaryEncoder;
use Sha512Hasher;
use MemoryStore;
use Read;
// 1. Create content
let blob = new;
// 2. Encode to deterministic bytes
let encoder = BinaryEncoder;
let bytes = encoder.encode_blob.unwrap;
// 3. Hash the bytes to get a content address
let hasher = Sha512Hasher;
let hash = hasher.hash.unwrap;
// 4. Store the encoded bytes in memory
let mut store = new;
store.put.unwrap;
// 5. Read back via streaming interface
let mut reader = store.get.unwrap;
let mut buf = Vecnew;
reader.read_to_end.unwrap;
assert_eq!;
Building a Commit Using Builders
use CommitBuilder;
use ;
let tree = from_bytes.unwrap;
let author = new.unwrap;
let committer = new.unwrap;
let commit = new
.tree
.author
.committer
.message
.build
.unwrap;
assert_eq!;
API Reference
All public items are exported from their respective modules. The recommended import paths are shown in each section.
Codec Module
Module path: libvctrl_core::codec
Contains the binary encoder and decoder.
BinaryEncoder
;
Implements libvctrl_handler::Encoder.
| Method | Description |
|---|---|
encode_blob(&self, blob: &Blob) -> Result<Vec<u8>, VctrlError> |
Encodes a Blob into versioned, length-prefixed binary. |
encode_tree(&self, tree: &Tree) -> Result<Vec<u8>, VctrlError> |
Encodes a Tree with entries, kinds, and hashes. |
encode_commit(&self, commit: &Commit) -> Result<Vec<u8>, VctrlError> |
Encodes a Commit with metadata and parents. |
encode_tag(&self, tag: &Tag) -> Result<Vec<u8>, VctrlError> |
Encodes a Tag with optional tagger. |
Example:
use ;
use BinaryEncoder;
let encoder = BinaryEncoder;
let blob = new;
let bytes = encoder.encode_blob.unwrap;
assert_eq!; // version byte
BinaryDecoder
;
Implements libvctrl_handler::Decoder.
| Method | Description |
|---|---|
decode_blob(&self, data: &[u8]) -> Result<Blob, VctrlError> |
Parses a binary blob. |
decode_tree(&self, data: &[u8]) -> Result<Tree, VctrlError> |
Parses a binary tree with sorted entries. |
decode_commit(&self, data: &[u8]) -> Result<Commit, VctrlError> |
Parses a binary commit with all fields. |
decode_tag(&self, data: &[u8]) -> Result<Tag, VctrlError> |
Parses a binary tag. |
Example:
use ;
use ;
let original = new;
let bytes = BinaryEncoder.encode_blob.unwrap;
let decoded = BinaryDecoder.decode_blob.unwrap;
assert_eq!;
Binary Format Specifications
All payloads start with a version byte (VERSION = 2), followed by little-endian integers and length-prefixed strings.
Blob format:
| Offset | Size | Field |
|---|---|---|
| 0 | 1 | Version |
| 1 | 8 | data_len (u64 LE) |
| 9 | data_len |
data |
Tree format:
| Offset | Size | Field |
|---|---|---|
| 0 | 1 | Version |
| 1 | 4 | entry_count (u32 LE) |
| 5 | varies | Repeated entries: name_len (u8), name, kind (u8), hash (64 bytes) |
Commit format:
| Field | Size |
|---|---|
| Version | 1 |
| Tree hash | 64 |
| Parent count | 1 |
| Parent hashes | 64 * count |
| Author name len + name | 1 + len |
| Author email len + email | 1 + len |
| Committer name len + name | 1 + len |
| Committer email len + email | 1 + len |
| Message len | 4 |
| Message | len |
| Timestamp | 8 |
| Timezone offset | 2 |
| Encoding len | 1 |
| Encoding (if len > 0) | len |
Tag format:
Similar to commit, but starts with name and target hash, then optional tagger.
The decoder enforces all system limits (MAX_BLOB_SIZE, MAX_MESSAGE_LENGTH, MAX_TREE_ENTRIES) and validates UTF-8 to prevent denial-of-service attacks.
Hash Module
Module path: libvctrl_core::hash
Sha512Hasher
;
Implements libvctrl_handler::Hasher.
Methods:
hash(&self, data: &[u8]) -> Result<Hash, VctrlError>
Computes a SHA-512 digest of the input using the libvctrl_sha512 crate and wraps it in a Hash. The digest length is always 64 bytes, so conversion cannot fail.
Example:
use Hasher;
use Sha512Hasher;
let hasher = Sha512Hasher;
let hash = hasher.hash.unwrap;
assert_eq!;
Object Module
Module path: libvctrl_core::object
Contains builders for ergonomic object construction.
BlobBuilder
Example:
use BlobBuilder;
let blob = new
.with_data
.build;
assert_eq!;
CommitBuilder
build() returns VctrlError::Other if any required field is missing.
Example:
use CommitBuilder;
use ;
let tree = from_bytes.unwrap;
let user = new.unwrap;
let commit = new
.tree
.author
.committer
.message
.build
.unwrap;
TagBuilder
Example:
use TagBuilder;
use Hash;
let target = from_bytes.unwrap;
let tag = new
.name
.target
.build
.unwrap;
assert_eq!;
TreeBuilder
build() delegates to Tree::new, enforcing sorted entry order.
Example:
use TreeBuilder;
use ;
let hash = from_bytes.unwrap;
let tree = new
.add_entry?
.add_entry?
.build
.unwrap;
# Ok::
TreeEntryBuilder
Example:
use TreeEntryBuilder;
use ;
let hash = from_bytes.unwrap;
let entry = new
.build
.unwrap;
Store Module
Module path: libvctrl_core::store
MemoryStore
Uses a HashMap<Hash, Vec<u8>> internally. get clones the stored bytes and wraps them in a std::io::Cursor, enabling streaming reads.
Example:
use MemoryStore;
use ;
use Read;
let mut store = new;
let hash = from_bytes.unwrap;
store.put.unwrap;
let mut reader = store.get.unwrap;
let mut buf = Vecnew;
reader.read_to_end.unwrap;
assert_eq!;
MemoryRefStore
Enforces name length limits and returns sorted reference names.
Example:
use MemoryRefStore;
use ;
let mut store = new;
let hash = from_bytes.unwrap;
store.set_ref.unwrap;
assert_eq!;
Validate Module
Module path: libvctrl_core::validate
validate_hash_bytes
pub const ;
Checks that a byte slice is exactly HASH_LENGTH (64) bytes long.
Example:
use validate_hash_bytes;
use HASH_LENGTH;
let valid = ;
assert!;
validate_name
;
Validates that a name is:
- Non-empty
- Not longer than
MAX_NAME_LENGTH - Does not contain
/ - Is not
.or..
Example:
use validate_name;
assert!;
assert!;
Testing
The crate includes unit tests and doctests. Run all tests with:
Run only doctests:
Run property-based tests (using proptest):
Run Clippy with strict lints:
CI/CD Pipeline
No CI/CD pipeline is currently configured in the repository.
If one is added, it should include the following stages:
graph LR
A[Push] --> B[Format Check]
B --> C[Clippy Lint]
C --> D[Run Tests]
D --> E[Build Docs]
E --> F[Publish to crates.io]
Deployment / Distribution
The crate is intended to be published to crates.io.
Release process:
- Update
versioninCargo.toml. - Update
CHANGELOG.md. - Run
cargo publish --dry-run. - Run
cargo publish.
After publication, documentation will be available at https://docs.rs/libvctrl_core.
Security & Compliance
libvctrl_core is a foundational layer for version control systems and adheres to strict security practices:
- No unsafe code:
#![forbid(unsafe_code)]guarantees memory safety. - DoS protection: Binary decoder enforces
MAX_BLOB_SIZE,MAX_TREE_ENTRIES, andMAX_MESSAGE_LENGTHbefore allocation. - Strict UTF-8 validation: All decoded strings are checked for valid UTF-8.
- Path traversal prevention:
validate_namerejects/,., and... - Deterministic serialization: Binary format ensures reproducible hashes.
- Streaming reads:
MemoryStore::getreturnsBox<dyn Read>to avoid loading large objects entirely into memory. - Audited cryptography:
Sha512Hasherdelegates tolibvctrl_sha512, which is pure Rust and auditable.
Downstream implementations must follow the guidelines in SECURITY.md at the workspace root.
Contributing
Contributions are welcome. Follow the workspace CONTRIBUTING.md.
For this crate, ensure:
- All public items have documentation with doctests.
- No
unsafecode. - Run
cargo fmt. - Run
cargo clippy --all-targets --all-features -- -D warnings. - All tests pass with
cargo test --all-features.
License
This project is licensed under the MIT License. See the LICENSE file in the workspace root for details.