dynpatch-core 0.1.0

Runtime engine for dynpatch - dynamic library loading, ABI validation, and transactional patching
Documentation
//! # dynpatch-core
//!
//! Runtime engine for safe live code reloading in Rust.
//!
//! This crate provides the core functionality for loading, validating, and activating
//! patches at runtime, with strong safety guarantees and transactional semantics.

pub mod loader;
pub mod registry;
pub mod validator;
pub mod error;
pub mod metrics;

pub use error::{Error, Result};
pub use loader::{PatchLoader, Library};
pub use registry::{PatchRegistry, PatchInfo, PatchRecord};
pub use validator::{Validator, ValidationConfig};

use dynpatch_interface::Version;
use tracing::{debug, info};

/// Initialize the dynpatch runtime with default settings
///
/// This sets up the global registry with sensible defaults.
/// For more control, use `RuntimeBuilder`.
pub fn init() {
    debug!("Initializing dynpatch runtime with defaults");
    info!("dynpatch v{} initialized", env!("CARGO_PKG_VERSION"));
    // Global registry is lazily initialized
}

/// Builder for configuring the dynpatch runtime
///
/// # Example
///
/// ```ignore
/// use dynpatch::RuntimeBuilder;
/// use dynpatch_interface::Version;
///
/// RuntimeBuilder::new()
///     .interface_version(Version::new(1, 0, 0))
///     .type_hash(0x1234567890abcdef)
///     .init();
/// ```
pub struct RuntimeBuilder {
    interface_version: Version,
    type_hash: u64,
}

impl RuntimeBuilder {
    pub fn new() -> Self {
        Self {
            interface_version: Version::new(0, 1, 0),
            type_hash: 0,
        }
    }

    /// Set the expected interface version
    pub fn interface_version(mut self, version: Version) -> Self {
        self.interface_version = version;
        self
    }

    /// Set the expected type hash
    pub fn type_hash(mut self, hash: u64) -> Self {
        self.type_hash = hash;
        self
    }

    /// Initialize the runtime with these settings
    pub fn init(self) {
        info!(
            "dynpatch runtime initialized: interface v{}, type_hash {:x}",
            self.interface_version, self.type_hash
        );
        // Note: In a full implementation, this would configure the global registry
        // For now, the global registry uses defaults
    }
}

impl Default for RuntimeBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// Reload a patch from the specified path
///
/// This is a convenience function that uses the global patch registry.
/// For more control, use `PatchRegistry::load` directly.
pub fn reload(path: &str) -> Result<()> {
    registry::global_registry().load(path)
}

/// Rollback to the previous patch
pub fn rollback() -> Result<()> {
    registry::global_registry().rollback()
}

/// Get information about the currently active patch
pub fn active_patch_info() -> Option<PatchInfo> {
    registry::global_registry().active_patch()
}

/// Get the history of all loaded patches
pub fn history() -> Vec<PatchRecord> {
    registry::global_registry().history()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_init() {
        init();
        // Should not panic
    }
}