libvctrl_handler
Version: 4.4.1
Crate type: Rust library (contracts only)
Workspace: libvcrtl
libvctrl_handler is the foundational contracts crate for the libvcrtl version control system. It defines the immutable data types, behavior traits, error model, and system-wide constants that all other workspace crates consume and implement.
The crate contains no concrete storage, hashing, serialization, networking, or signing implementations. Instead, it provides a precise, well-documented abstraction layer that enforces correct, secure, and interoperable behavior across the entire version control stack.
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_handler is the contract layer of the libvcrtl version control system. It serves as the single source of truth for:
- Domain objects:
Blob,Tree,TreeEntry,Commit,CommitMeta,Tag,Hash,UserID - Logical object kinds:
EntryKind - System limits:
HASH_LENGTH,MAX_NAME_LENGTH,MAX_BLOB_SIZE,MAX_TREE_ENTRIES,MAX_MESSAGE_LENGTH - Behavior interfaces:
ObjectStore,RefStore,Hasher,Encoder,Decoder,Signer,Verifier,Transport - Unified error type:
VctrlError - Validation helpers for names, tree entries, hashes, and sorted tree ordering
Because the crate is implementation-free, downstream crates can freely combine different storage backends, cryptographic algorithms, serialization formats, and transport mechanisms without modifying the core domain model.
The crate enforces extremely strict code quality standards:
#![forbid(unsafe_code)]#![deny(missing_docs)]#![deny(clippy::all, clippy::pedantic, clippy::cargo)]#![warn(clippy::nursery)]- All public items carry extensive doctests
System Architecture
Workspace Context
libvctrl_handler is one crate inside the libvcrtl workspace. It sits at the bottom of the dependency graph as the contracts crate. All higher-level crates depend on it.
graph TD
subgraph libvcrtl_workspace
HANDLER[libvctrl_handler<br/>Contracts and Types]
CORE[libvctrl_core<br/>Core engine]
PLUMBING[libvctrl_plumbing<br/>Low-level commands]
PORCELAIN[libvctrl_porcelain<br/>User-facing commands]
SHA512[libvctrl_sha512<br/>Hash implementation]
DOCS[libvctrl_docs<br/>Documentation tools]
LIBVCTRL[libvctrl<br/>Main CLI]
end
HANDLER --> CORE
HANDLER --> PLUMBING
HANDLER --> PORCELAIN
HANDLER --> SHA512
HANDLER --> DOCS
HANDLER --> LIBVCTRL
CORE --> PLUMBING
PORCELAIN --> PLUMBING
LIBVCTRL --> PORCELAIN
LIBVCTRL --> CORE
libvctrl_handler defines what a version control object is and what operations a backend must support. It never defines how those operations are performed.
Internal Module Architecture
The crate is split into six public modules:
graph LR
ROOT[libvctrl_handler root]
CONSTANTS[constants]
ENUMS[enums]
ERRORS[errors]
MACROS[macros]
TYPES[types]
TRAITS[traits]
ROOT --> CONSTANTS
ROOT --> ENUMS
ROOT --> ERRORS
ROOT --> MACROS
ROOT --> TYPES
ROOT --> TRAITS
ENUMS --> CONSTANTS
ERRORS --> TYPES
TYPES --> CONSTANTS
TYPES --> ENUMS
TYPES --> ERRORS
TRAITS --> TYPES
TRAITS --> ERRORS
constants: Centralizes all numeric limits, hash length, and raw Unix mode bits.enums: DefinesEntryKind, the logical object discriminator.errors: DefinesVctrlError, the unified error type.macros: Exports helper macros for error construction and internal comparisons.types: Defines immutable domain structs and validation helpers.traits: Defines all behavior contracts.
Object and Data Flow
The following sequence illustrates how concrete implementations of the crate contracts might interact when storing a blob and creating a commit.
sequenceDiagram
participant App as Downstream Application
participant Hasher as Hasher impl
participant Store as ObjectStore impl
participant Enc as Encoder impl
participant Ref as RefStore impl
App->>Hasher: hash(blob.data())
Hasher-->>App: Hash
App->>Enc: encode_blob(&blob)
Enc-->>App: Vec<u8>
App->>Store: put(&hash, &bytes)
App->>Store: put(&tree_hash, &tree_bytes)
App->>Enc: encode_commit(&commit)
Enc-->>App: Vec<u8>
App->>Store: put(&commit_hash, &commit_bytes)
App->>Ref: set_ref("refs/heads/main", &commit_hash)
Core Features
- Immutable domain model: All core types are constructed once and cannot be mutated, preserving content-addressing invariants.
- Unified error handling: Every fallible operation returns
VctrlError, with support for source-error chaining and comparison. - Streaming object reads:
ObjectStore::getreturnsBox<dyn Read>, avoiding large contiguous allocations. - Sorted tree enforcement: Tree entries must be lexicographically sorted and duplicate-free, guaranteeing deterministic hashing.
- Strict validation: Hash lengths, name lengths, email presence, tree entry names, and tree ordering are validated at construction time.
- Separation of data and behavior: Data structs never contain implementation logic; behavior is defined entirely through traits.
- Compile-time safety:
#![forbid(unsafe_code)]ensures the crate contains no unsafe Rust. - Comprehensive documentation: All public items are fully documented and include runnable doctests.
- Non-exhaustive API evolution:
EntryKindandVctrlErrorare#[non_exhaustive], allowing backward-compatible additions.
Technology Stack
- Language: Rust (edition 2018 or later; workspace uses Rust 1.96.0)
- Standard library only: No external dependencies for the contracts themselves.
- Traits:
std::io::Readfor streaming object reads - Error handling:
std::error::Errorintegration - Macros:
macro_rules!for internal and public helper macros - Documentation: Rustdoc with embedded doctests
Project Structure
The workspace layout is as follows:
libvcrtl/
├── Cargo.toml
├── Cargo.lock
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── SECURITY.md
├── Makefile
├── scripts/
├── libvctrl/
├── libvctrl_core/
├── libvctrl_docs/
├── libvctrl_handler/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ ├── constants.rs
│ ├── errors.rs
│ ├── macros.rs
│ ├── enums/
│ │ ├── mod.rs
│ │ └── core/
│ │ ├── mod.rs
│ │ └── entry_kind.rs
│ ├── traits/
│ │ ├── mod.rs
│ │ └── core/
│ │ ├── mod.rs
│ │ ├── object_store.rs
│ │ ├── ref_store.rs
│ │ ├── hasher.rs
│ │ ├── encoder.rs
│ │ ├── decoder.rs
│ │ ├── signer.rs
│ │ ├── verifier.rs
│ │ └── transport.rs
│ └── types/
│ ├── mod.rs
│ └── core/
│ ├── mod.rs
│ ├── blob.rs
│ ├── tree.rs
│ ├── commit.rs
│ ├── tag.rs
│ ├── hash.rs
│ └── user_id.rs
├── libvctrl_plumbing/
├── libvctrl_porcelain/
└── libvctrl_sha512/
The libvctrl_handler/src tree is:
src/
├── constants.rs
├── enums/
│ ├── core/
│ │ ├── mod.rs
│ │ └── entry_kind.rs
│ └── mod.rs
├── errors.rs
├── lib.rs
├── macros.rs
├── traits/
│ ├── core/
│ │ ├── mod.rs
│ │ ├── decoder.rs
│ │ ├── encoder.rs
│ │ ├── hasher.rs
│ │ ├── object_store.rs
│ │ ├── ref_store.rs
│ │ ├── signer.rs
│ │ ├── transport.rs
│ │ └── verifier.rs
│ └── mod.rs
└── types/
├── core/
│ ├── mod.rs
│ ├── blob.rs
│ ├── commit.rs
│ ├── hash.rs
│ ├── tag.rs
│ ├── tree.rs
│ └── user_id.rs
└── mod.rs
Getting Started
Prerequisites
- Rust toolchain
1.96.0or newer - Cargo
- No external services are required to build or document this crate
Because libvctrl_handler is a pure contracts crate, it has no runtime dependencies beyond the Rust standard library.
Installation
Add libvctrl_handler to your Cargo.toml:
[]
= "4.4.0"
Or use Cargo:
When the crate is published to crates.io, you can also view rendered API documentation at https://docs.rs/libvctrl_handler.
Configuration
No configuration is required. The crate defines only abstract contracts and immutable data types. Downstream crates must choose or implement concrete backends for the exported traits:
ObjectStoreRefStoreHasherEncoderDecoderSignerVerifierTransport
Usage
Basic Object Construction
use ;
let blob = new;
let hash = from_bytes.unwrap;
let user = new.unwrap;
let tree = new.unwrap;
let commit = new;
let tag = new.unwrap;
let kind = Blob;
Implementing a Trait
All behavior contracts are simple Rust traits. For example, a minimal Hasher:
use ;
;
The complete API reference below provides full implementations for every trait.
API Reference
All public items are re-exported at the crate root. You can use either:
use Blob;
or
use Blob;
The crate root re-exports are the recommended interface.
Modules
The crate contains six public modules.
constants
Centralizes all system-wide magic numbers and structural limits.
use ;
assert_eq!;
assert_eq!;
Submodule: entry_mode holds raw Unix mode bits.
enums
Defines EntryKind, the logical object discriminator.
use EntryKind;
assert_ne!;
errors
Defines VctrlError, the unified error type returned by all fallible operations.
use VctrlError;
let err = Other;
macros
Exports helper macros for ergonomic error construction.
use vctrl_error_other;
let err = vctrl_error_other!;
traits
Contains all behavior contracts, each in its own submodule under traits::core.
use Hasher;
All traits are also re-exported at the crate root:
use ;
types
Contains all immutable domain data structures and internal validation helpers.
use ;
Constants
All constants are defined in constants.rs and re-exported at the crate root.
HASH_LENGTH
pub const HASH_LENGTH: usize = 64;
The expected length of a Hash in bytes. This is 64 bytes, equivalent to 512 bits, aligning with SHA-512 or BLAKE3 extended output.
Example:
use ;
let hash = from_bytes.unwrap;
assert_eq!;
MAX_NAME_LENGTH
pub const MAX_NAME_LENGTH: u64 = 255;
Maximum byte length for names such as branches, tags, and file entries. This matches common filesystem filename limits.
MAX_BLOB_SIZE
pub const MAX_BLOB_SIZE: u64 = 100 * 1024 * 1024;
Maximum allowed size in bytes for a single Blob. The 100 MiB limit prevents memory exhaustion during hashing and encoding while still supporting large binary assets.
MAX_TREE_ENTRIES
pub const MAX_TREE_ENTRIES: u64 = 100_000;
Maximum number of entries allowed in a single Tree.
MAX_MESSAGE_LENGTH
pub const MAX_MESSAGE_LENGTH: u64 = 1024 * 1024;
Maximum byte length for commit or tag messages. The 1 MiB limit allows detailed messages while preventing abuse via excessive payloads.
entry_mode
Submodule containing raw Unix filesystem mode bits used in serialized tree formats.
These constants represent the serialized format. They are separate from the logical EntryKind enum, allowing different backends to map their own mode systems to a uniform set of kinds.
Enums
EntryKind
Represents the logical kind of an entry in a version control tree.
Variants:
| Variant | Description |
|---|---|
Blob |
Regular, non-executable file content. |
Executable |
Executable file content. The underlying data is still a Blob, but the executable flag is stored at tree-entry level. |
Symlink |
Symbolic link. The blob content is the target path. |
Tree |
Subdirectory. Points to another Tree object. |
Submodule |
Submodule reference. Points to a commit in a separate repository. |
Design rationale:
#[non_exhaustive]ensures downstream code cannot exhaustively match without a wildcard arm, allowing future variants to be added without breaking API compatibility.CopyandClonekeep the enum lightweight.Hash,PartialEq, andEqallow use as keys in collections.
Example:
use EntryKind;
Errors
VctrlError
The unified error type returned by all fallible operations in the crate.
Variants:
| Variant | Trigger |
|---|---|
InvalidHashLength(usize) |
Constructing a Hash from a byte slice of wrong length. |
InvalidName(String) |
Empty or excessively long names in branches, tags, tree entries, etc. |
InvalidEmail(String) |
Empty email address in UserID. |
ObjectNotFound(Hash) |
Requested object not present in an ObjectStore. |
RefNotFound(String) |
Requested reference not present in a RefStore. |
CorruptedData(String) |
Malformed serialized data. |
IoError(std::io::Error) |
Wraps an underlying I/O error. |
SerializationError(String) |
Errors from encoding or decoding. |
Other(String) |
Catch-all for miscellaneous errors. |
Implemented traits:
Display: Human-readable messages with contextual details.Error:source()returns the wrapped I/O error only forIoError.Clone: Manual implementation preserves I/O error kind and message without requiringstd::io::Errorto beClone.PartialEq/Eq: Allows comparisons by variant and payload. ForIoError, equality is based on error kind and display message.
Example:
use ;
use Error;
let io = new;
let err = IoError;
assert!;
let hash = from_bytes.unwrap;
let not_found = ObjectNotFound;
assert!;
Traits
All traits are defined under traits::core and re-exported at the crate root.
ObjectStore
Content-addressable object database.
put: Stores raw serialized object bytes under a hash.get: Retrieves an object as a streamingRead. This avoids large contiguous allocations.delete: Removes an object.exists: Checks presence without retrieving the full object.
Example in-memory implementation:
use ;
use HashMap;
use Read;
;
RefStore
Named reference management (branches, tags, HEAD).
Example in-memory implementation:
use ;
use HashMap;
;
Hasher
Cryptographic content hashing.
Example dummy hasher:
use ;
;
Encoder
Serialization of version control objects into byte vectors.
Example dummy encoder:
use ;
;
Decoder
Deserialization of version control objects from byte slices.
Example dummy decoder:
use ;
;
Signer
Cryptographic signing of data.
Example dummy signer:
use ;
;
Verifier
Cryptographic signature verification.
Example dummy verifier:
use ;
;
Transport
Remote object synchronization.
Example in-memory transport:
use ;
use HashMap;
;
Types
All domain types are immutable after construction and validate their inputs.
Blob
A binary large object holding raw byte content. It owns its data and provides read-only access. Blobs are content-addressed, so mutation is intentionally impossible.
Example:
use Blob;
let blob = new;
assert_eq!;
assert_eq!;
assert!;
TreeEntry
A single entry in a Tree. The name must be non-empty, not exceed MAX_NAME_LENGTH, and cannot contain /, ., or .. as a component.
Example:
use ;
let hash = from_bytes.unwrap;
let entry = new.unwrap;
assert_eq!;
Tree
A sorted list of tree entries representing a directory snapshot. Entries must be strictly sorted lexicographically by name. Duplicate names or unsorted entries cause VctrlError::InvalidName.
Example:
use ;
let hash = from_bytes.unwrap;
let entries = vec!;
let tree = new.unwrap;
assert_eq!;
CommitMeta
Optional metadata for a commit or tag.
Example:
use CommitMeta;
let meta = CommitMeta ;
Commit
A commit object representing a point in version history.
newcreates a commit with zeroed timestamp/offset and no encoding.with_metaaccepts full metadata.
Example:
use ;
let tree = from_bytes.unwrap;
let author = new.unwrap;
let committer = new.unwrap;
let meta = CommitMeta ;
let commit = with_meta;
assert_eq!;
assert_eq!;
Tag
A named reference to a specific object, commonly a commit.
Example:
use ;
let target = from_bytes.unwrap;
let tagger = new.unwrap;
let meta = CommitMeta ;
let tag = with_meta.unwrap;
assert_eq!;
assert_eq!;
Hash
;
A fixed-size 64-byte hash used for content addressing. Stored inline for stack allocation and Copy.
Formatting:
Displayproduces the full 128-character lowercase hexadecimal string.Debugshows the first 8 bytes in hexadecimal followed by an ellipsis.
Example:
use Hash;
let hash = from_bytes.unwrap;
assert_eq!;
let hex = format!;
assert_eq!;
let debug = format!;
assert!;
UserID
A validated user identity consisting of a name and an email address.
Validation rules:
namemust be non-empty and not exceedMAX_NAME_LENGTH.emailmust be non-empty.
Example:
use UserID;
let user = new.unwrap;
assert_eq!;
assert_eq!;
Macros
vctrl_error_other!
Creates a VctrlError::Other variant with a formatted message.
Example:
use vctrl_error_other;
let err = vctrl_error_other!;
assert_eq!;
string_payload_variants!
Helper macro used in the PartialEq implementation of VctrlError. It extracts the string payload from all variants that carry a String. Although exported, it is primarily intended for internal use.
Testing
The crate uses doctests embedded in documentation and standard unit tests.
Run all tests:
Run only doctests:
All public items must have doctests. When adding a new item, ensure every code example compiles and passes under cargo test --doc.
Run Clippy with strict lints:
CI/CD Pipeline
No CI/CD pipeline is currently configured in the repository.
When a pipeline is introduced, the following stages are recommended:
graph LR
A[Push to main] --> B[Format Check]
B --> C[Clippy Lint]
C --> D[Run Tests]
D --> E[Build Docs]
E --> F[Publish to crates.io]
Recommended commands per stage:
- Format:
cargo fmt --check - Lint:
cargo clippy --all-targets --all-features -- -D warnings - Tests:
cargo test --all-features - Docs:
cargo doc --no-deps - Publish:
cargo publish
Deployment / Distribution
The crate is published to crates.io.
Release process:
- Update
versioninCargo.toml. - Update
CHANGELOG.mdwith all notable changes. - Run
cargo publish --dry-runto verify packaging. - Run
cargo publishwith a validCRATES_IO_TOKEN.
After publication, the rendered documentation is automatically available at:
https://crates.io/crates/libvctrl_handlerhttps://docs.rs/libvctrl_handler
Security & Compliance
libvctrl_handler is a security-sensitive foundational crate. The following measures are enforced:
- No unsafe code:
#![forbid(unsafe_code)]prevents any unsafe Rust from entering the crate. - Immutability: Once constructed, domain objects cannot be mutated, preventing hash corruption.
- Input validation: All constructors validate hash length, name length, email presence, tree ordering, and forbidden characters.
- Resource limits: Constants such as
MAX_BLOB_SIZEandMAX_TREE_ENTRIESprevent denial-of-service via oversized objects. - Cryptographic abstraction:
SignerandVerifierallow downstream crates to implement strong algorithms like Ed25519, RSA, or BLAKE3 signatures without weakening the core. - No implicit I/O or network: The crate itself performs no file or network operations. All such behavior is isolated behind traits, minimizing attack surface.
- Non-exhaustive error and enum types: Allows adding new security-related variants without breaking downstream code.
Downstream implementations must follow the guidelines in SECURITY.md at the workspace root.
Contributing
Contributions are welcome. Please follow the workspace CONTRIBUTING.md.
Key development standards for this crate:
- All public items must have
missing_docs-compliant documentation with doctests. - Strict Clippy lints are enforced:
clippy::allclippy::pedanticclippy::cargoclippy::nurseryis treated as a warning to avoid breakage from unstable toolchain updates.
unsafecode is forbidden.- Run
cargo fmtbefore submitting changes. - Run
cargo clippy --all-targets --all-features -- -D warningsbefore opening a pull request. - Ensure all examples compile and pass under
cargo test --doc.
License
This project is licensed under the MIT License. See the LICENSE file in the workspace root for details.