use crate::runtime::values::Value;
use crate::ffi::interface::InterfaceType;
#[derive(Debug, Clone)]
pub struct ServiceMetadata {
pub name: String,
pub function_names: Vec<String>,
pub has_network_operations: bool,
pub has_compute_operations: bool,
pub estimated_call_frequency: CallFrequency,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CallFrequency {
Low, Medium, High, }
impl ServiceMetadata {
pub fn detect_interface_type(&self) -> InterfaceType {
if self.estimated_call_frequency == CallFrequency::High {
return InterfaceType::FFI;
}
if self.has_network_operations && !self.has_compute_operations {
return InterfaceType::HTTP;
}
if self.has_compute_operations && !self.has_network_operations {
return InterfaceType::FFI;
}
InterfaceType::Both
}
pub fn analyze_function(function_name: &str) -> (bool, bool) {
let network_patterns = [
"chain::", "database::", "network_", "remote_",
"fetch", "request", "api_", "http_", "web_",
];
let compute_patterns = [
"hash", "sign", "verify", "encrypt", "decrypt",
"compute", "calculate", "process", "transform",
"batch_", "parallel_", "fast_", "crypto::",
];
let has_network = network_patterns.iter()
.any(|pattern| function_name.contains(pattern));
let has_compute = compute_patterns.iter()
.any(|pattern| function_name.contains(pattern));
(has_network, has_compute)
}
}
pub struct InterfaceSelector {
default_interface: InterfaceType,
service_metadata: std::collections::HashMap<String, ServiceMetadata>,
}
impl InterfaceSelector {
pub fn new() -> Self {
Self {
default_interface: InterfaceType::Both, service_metadata: std::collections::HashMap::new(),
}
}
pub fn register_service(&mut self, metadata: ServiceMetadata) {
self.service_metadata.insert(metadata.name.clone(), metadata);
}
pub fn select_interface(
&self,
service_name: &str,
function_name: &str,
_args: &[Value],
) -> InterfaceType {
if let Some(metadata) = self.service_metadata.get(service_name) {
let service_interface = metadata.detect_interface_type();
let (has_network, has_compute) = ServiceMetadata::analyze_function(function_name);
if has_network && !has_compute {
return InterfaceType::HTTP;
}
if has_compute && !has_network {
return InterfaceType::FFI;
}
return service_interface;
}
let (has_network, has_compute) = ServiceMetadata::analyze_function(function_name);
if has_network && !has_compute {
InterfaceType::HTTP
} else if has_compute && !has_network {
InterfaceType::FFI
} else {
self.default_interface
}
}
pub fn set_default(&mut self, interface: InterfaceType) {
self.default_interface = interface;
}
pub fn default_interface(&self) -> InterfaceType {
self.default_interface
}
pub fn service_count(&self) -> usize {
self.service_metadata.len()
}
pub fn has_service(&self, service_name: &str) -> bool {
self.service_metadata.contains_key(service_name)
}
}
impl Default for InterfaceSelector {
fn default() -> Self {
Self::new()
}
}