use crate::ffi::interface::InterfaceType;
use crate::runtime::values::Value;
#[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()
}
}