use crate::{ComponentDependencies, FunctionName, InferredExpr, RibCompilationError};
use golem_wasm_ast::analysis::AnalysedType;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkerFunctionsInRib {
pub function_calls: Vec<WorkerFunctionType>,
}
impl WorkerFunctionsInRib {
pub fn from_inferred_expr(
inferred_expr: &InferredExpr,
component_dependency: &ComponentDependencies,
) -> Result<Option<WorkerFunctionsInRib>, RibCompilationError> {
let worker_invoke_registry_keys = inferred_expr.worker_invoke_registry_keys();
let mut function_calls = vec![];
for key in worker_invoke_registry_keys {
let (_, function_type) = component_dependency
.get_function_type(&None, &key)
.map_err(|e| RibCompilationError::RibStaticAnalysisError(e.to_string()))?;
let function_call_in_rib = WorkerFunctionType {
function_name: key,
parameter_types: function_type
.parameter_types
.iter()
.map(|param| AnalysedType::try_from(param).unwrap())
.collect(),
return_type: function_type
.return_type
.as_ref()
.map(|return_type| AnalysedType::try_from(return_type).unwrap()),
};
function_calls.push(function_call_in_rib)
}
if function_calls.is_empty() {
Ok(None)
} else {
Ok(Some(WorkerFunctionsInRib { function_calls }))
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WorkerFunctionType {
pub function_name: FunctionName,
pub parameter_types: Vec<AnalysedType>,
pub return_type: Option<AnalysedType>,
}
#[cfg(feature = "protobuf")]
mod protobuf {
use crate::{FunctionName, WorkerFunctionType, WorkerFunctionsInRib};
use golem_api_grpc::proto::golem::rib::WorkerFunctionType as WorkerFunctionTypeProto;
use golem_api_grpc::proto::golem::rib::WorkerFunctionsInRib as WorkerFunctionsInRibProto;
use golem_wasm_ast::analysis::AnalysedType;
impl TryFrom<WorkerFunctionsInRibProto> for WorkerFunctionsInRib {
type Error = String;
fn try_from(value: WorkerFunctionsInRibProto) -> Result<Self, Self::Error> {
let function_calls_proto = value.function_calls;
let function_calls = function_calls_proto
.iter()
.map(|worker_function_type_proto| {
WorkerFunctionType::try_from(worker_function_type_proto.clone())
})
.collect::<Result<_, _>>()?;
Ok(Self { function_calls })
}
}
impl From<WorkerFunctionsInRib> for WorkerFunctionsInRibProto {
fn from(value: WorkerFunctionsInRib) -> Self {
WorkerFunctionsInRibProto {
function_calls: value
.function_calls
.iter()
.map(|x| WorkerFunctionTypeProto::from(x.clone()))
.collect(),
}
}
}
impl TryFrom<WorkerFunctionTypeProto> for WorkerFunctionType {
type Error = String;
fn try_from(value: WorkerFunctionTypeProto) -> Result<Self, Self::Error> {
let return_type = value
.return_type
.as_ref()
.map(AnalysedType::try_from)
.transpose()?;
let parameter_types = value
.parameter_types
.iter()
.map(AnalysedType::try_from)
.collect::<Result<_, _>>()?;
let function_key_type = value.function_name.and_then(|x| x.function_name).ok_or(
"WorkerFunctionTypeProto function_key must have a function_name".to_string(),
)?;
let function_name = FunctionName::try_from(function_key_type)
.map_err(|e| format!("Failed to convert function key: {e}"))?;
Ok(Self {
function_name,
return_type,
parameter_types,
})
}
}
impl From<WorkerFunctionType> for WorkerFunctionTypeProto {
fn from(value: WorkerFunctionType) -> Self {
let function_key =
golem_api_grpc::proto::golem::rib::function_name_type::FunctionName::from(
value.function_name,
);
let function_name_type = golem_api_grpc::proto::golem::rib::FunctionNameType {
function_name: Some(function_key),
};
WorkerFunctionTypeProto {
function_name: Some(function_name_type),
parameter_types: value
.parameter_types
.iter()
.map(|analysed_type| analysed_type.into())
.collect(),
return_type: value
.return_type
.as_ref()
.map(|analysed_type| analysed_type.into()),
}
}
}
}