#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::Result;
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
pub trait Service: Send + Sync {
fn service_name(&self) -> &'static str;
fn initialize(&mut self) -> Result<()> {
Ok(())
}
fn health_check(&self) -> Result<()> {
Ok(())
}
fn shutdown(&mut self) -> Result<()> {
Ok(())
}
}
#[async_trait::async_trait]
pub trait AnalysisService: Service {
type Input;
type Output;
type Error: std::error::Error + Send + Sync;
async fn analyze(&self, input: Self::Input) -> Result<Self::Output, Self::Error>;
fn capabilities(&self) -> AnalysisCapabilities {
AnalysisCapabilities::default()
}
}
#[derive(Debug, Clone)]
pub struct AnalysisCapabilities {
pub supports_batch: bool,
pub supports_streaming: bool,
pub max_file_size: Option<usize>,
pub supported_languages: Vec<String>,
}
impl Default for AnalysisCapabilities {
fn default() -> Self {
Self {
supports_batch: true,
supports_streaming: false,
max_file_size: None,
supported_languages: vec!["rust".to_string()],
}
}
}
#[derive(Clone)]
pub struct ServiceRegistry {
services: Arc<RwLock<HashMap<TypeId, Box<dyn Any + Send + Sync>>>>,
service_names: Arc<RwLock<HashMap<TypeId, &'static str>>>,
}
impl ServiceRegistry {
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Self {
Self {
services: Arc::new(RwLock::new(HashMap::new())),
service_names: Arc::new(RwLock::new(HashMap::new())),
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn register<T: Service + 'static>(&self, mut service: T) -> Result<()> {
service.initialize()?;
let service_name = service.service_name();
let type_id = TypeId::of::<T>();
{
let mut services = self.services.write().expect("internal error");
services.insert(type_id, Box::new(Arc::new(service)));
}
{
let mut names = self.service_names.write().expect("internal error");
names.insert(type_id, service_name);
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn get<T: Service + 'static>(&self) -> Result<Arc<T>> {
let type_id = TypeId::of::<T>();
let services = self.services.read().expect("internal error");
let service = services
.get(&type_id)
.ok_or_else(|| anyhow::anyhow!("Service not found: {}", std::any::type_name::<T>()))?;
let service = service.downcast_ref::<Arc<T>>().ok_or_else(|| {
anyhow::anyhow!("Service type mismatch for: {}", std::any::type_name::<T>())
})?;
Ok(Arc::clone(service))
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn has<T: Service + 'static>(&self) -> bool {
let type_id = TypeId::of::<T>();
let services = self.services.read().expect("internal error");
services.contains_key(&type_id)
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn list_services(&self) -> Vec<&'static str> {
let names = self.service_names.read().expect("internal error");
names.values().copied().collect()
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn health_check_all(&self) -> Result<Vec<(&'static str, Result<()>)>> {
Ok(vec![])
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn shutdown_all(&mut self) -> Result<()> {
Ok(())
}
}
impl Default for ServiceRegistry {
fn default() -> Self {
Self::new()
}
}
pub struct ServiceRegistryBuilder {
registry: ServiceRegistry,
}
impl ServiceRegistryBuilder {
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Self {
Self {
registry: ServiceRegistry::new(),
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn with_service<T: Service + 'static>(self, service: T) -> Result<Self> {
self.registry.register(service)?;
Ok(self)
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn build(self) -> ServiceRegistry {
self.registry
}
}
impl Default for ServiceRegistryBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
struct TestService {
name: &'static str,
}
struct AnotherTestService {
name: &'static str,
}
impl Service for TestService {
fn service_name(&self) -> &'static str {
self.name
}
}
impl Service for AnotherTestService {
fn service_name(&self) -> &'static str {
self.name
}
}
#[test]
fn test_service_registry_creation() {
let registry = ServiceRegistry::new();
assert_eq!(registry.list_services().len(), 0);
}
#[test]
fn test_service_registration() -> Result<()> {
let registry = ServiceRegistry::new();
let service = TestService {
name: "test_service",
};
registry.register(service)?;
assert!(registry.has::<TestService>());
assert_eq!(registry.list_services(), vec!["test_service"]);
Ok(())
}
#[test]
fn test_service_retrieval() -> Result<()> {
let registry = ServiceRegistry::new();
let service = TestService {
name: "test_service",
};
registry.register(service)?;
let retrieved = registry.get::<TestService>()?;
assert_eq!(retrieved.service_name(), "test_service");
Ok(())
}
#[test]
fn test_service_builder() -> Result<()> {
let registry = ServiceRegistryBuilder::new()
.with_service(TestService { name: "service1" })?
.with_service(AnotherTestService { name: "service2" })?
.build();
assert_eq!(registry.list_services().len(), 2);
Ok(())
}
#[test]
fn test_analysis_capabilities_default() {
let caps = AnalysisCapabilities::default();
assert!(caps.supports_batch);
assert!(!caps.supports_streaming);
assert!(caps.max_file_size.is_none());
assert!(caps.supported_languages.contains(&"rust".to_string()));
}
#[test]
fn test_analysis_capabilities_clone() {
let caps = AnalysisCapabilities {
supports_batch: false,
supports_streaming: true,
max_file_size: Some(1024),
supported_languages: vec!["python".to_string()],
};
let cloned = caps.clone();
assert!(!cloned.supports_batch);
assert!(cloned.supports_streaming);
assert_eq!(cloned.max_file_size, Some(1024));
}
#[test]
fn test_analysis_capabilities_debug() {
let caps = AnalysisCapabilities::default();
let debug = format!("{:?}", caps);
assert!(debug.contains("AnalysisCapabilities"));
}
#[test]
fn test_service_registry_default() {
let registry = ServiceRegistry::default();
assert!(registry.list_services().is_empty());
}
#[test]
fn test_service_registry_has_not_registered() {
let registry = ServiceRegistry::new();
assert!(!registry.has::<TestService>());
}
#[test]
fn test_service_registry_get_not_registered() {
let registry = ServiceRegistry::new();
let result = registry.get::<TestService>();
assert!(result.is_err());
}
#[test]
fn test_service_registry_multiple_services() -> Result<()> {
let registry = ServiceRegistry::new();
registry.register(TestService { name: "service1" })?;
registry.register(AnotherTestService { name: "service2" })?;
assert!(registry.has::<TestService>());
assert!(registry.has::<AnotherTestService>());
assert_eq!(registry.list_services().len(), 2);
Ok(())
}
#[test]
fn test_service_registry_clone() -> Result<()> {
let registry = ServiceRegistry::new();
registry.register(TestService { name: "test" })?;
let cloned = registry.clone();
assert!(cloned.has::<TestService>());
assert_eq!(cloned.list_services().len(), 1);
Ok(())
}
#[test]
fn test_service_registry_builder_new() {
let builder = ServiceRegistryBuilder::new();
let registry = builder.build();
assert!(registry.list_services().is_empty());
}
#[test]
fn test_service_registry_builder_default() {
let builder = ServiceRegistryBuilder::default();
let registry = builder.build();
assert!(registry.list_services().is_empty());
}
#[test]
fn test_service_registry_builder_chain() -> Result<()> {
let registry = ServiceRegistryBuilder::new()
.with_service(TestService { name: "a" })?
.build();
assert_eq!(registry.list_services().len(), 1);
Ok(())
}
struct DefaultMethodsService;
impl Service for DefaultMethodsService {
fn service_name(&self) -> &'static str {
"default_methods"
}
}
#[test]
fn test_service_health_check_default() {
let service = DefaultMethodsService;
assert!(service.health_check().is_ok());
}
#[test]
fn test_service_shutdown_default() {
let mut service = DefaultMethodsService;
assert!(service.shutdown().is_ok());
}
#[test]
fn test_service_initialize_default() {
let mut service = DefaultMethodsService;
assert!(service.initialize().is_ok());
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}