use crate::{ComponentDependencyKey, DynamicParsedFunctionName, Expr};
use crate::{FullyQualifiedResourceConstructor, VariableId};
use std::fmt::Display;
#[derive(Debug, Hash, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum CallType {
Function {
component_info: Option<ComponentDependencyKey>,
instance_identifier: Option<Box<InstanceIdentifier>>,
function_name: DynamicParsedFunctionName,
},
VariantConstructor(String),
EnumConstructor(String),
InstanceCreation(InstanceCreationType),
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum InstanceIdentifier {
WitWorker {
variable_id: Option<VariableId>,
worker_name: Option<Box<Expr>>,
},
WitResource {
variable_id: Option<VariableId>,
worker_name: Option<Box<Expr>>,
resource_name: String,
},
}
impl InstanceIdentifier {
pub fn worker_name_mut(&mut self) -> Option<&mut Box<Expr>> {
match self {
InstanceIdentifier::WitWorker { worker_name, .. } => worker_name.as_mut(),
InstanceIdentifier::WitResource { worker_name, .. } => worker_name.as_mut(),
}
}
pub fn worker_name(&self) -> Option<&Expr> {
match self {
InstanceIdentifier::WitWorker { worker_name, .. } => worker_name.as_deref(),
InstanceIdentifier::WitResource { worker_name, .. } => worker_name.as_deref(),
}
}
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum InstanceCreationType {
WitWorker {
component_info: Option<ComponentDependencyKey>,
worker_name: Option<Box<Expr>>,
},
WitResource {
component_info: Option<ComponentDependencyKey>,
module: Option<InstanceIdentifier>,
resource_name: FullyQualifiedResourceConstructor,
},
}
impl InstanceCreationType {
pub fn worker_name(&self) -> Option<Expr> {
match self {
InstanceCreationType::WitWorker { worker_name, .. } => worker_name.as_deref().cloned(),
InstanceCreationType::WitResource { module, .. } => {
let r = module.as_ref().and_then(|m| m.worker_name());
r.cloned()
}
}
}
}
impl CallType {
pub fn function_name(&self) -> Option<DynamicParsedFunctionName> {
match self {
CallType::Function { function_name, .. } => Some(function_name.clone()),
_ => None,
}
}
pub fn worker_expr(&self) -> Option<&Expr> {
match self {
CallType::Function {
instance_identifier,
..
} => {
let module = instance_identifier.as_ref()?;
module.worker_name()
}
_ => None,
}
}
pub fn function_call(
function: DynamicParsedFunctionName,
component_info: Option<ComponentDependencyKey>,
) -> CallType {
CallType::Function {
instance_identifier: None,
function_name: function,
component_info,
}
}
pub fn function_call_with_worker(
module: InstanceIdentifier,
function: DynamicParsedFunctionName,
component_info: Option<ComponentDependencyKey>,
) -> CallType {
CallType::Function {
instance_identifier: Some(Box::new(module)),
function_name: function,
component_info,
}
}
pub fn is_resource_method(&self) -> bool {
match self {
CallType::Function { function_name, .. } => function_name
.to_parsed_function_name()
.function
.resource_method_name()
.is_some(),
_ => false,
}
}
}
impl Display for CallType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CallType::Function { function_name, .. } => write!(f, "{function_name}"),
CallType::VariantConstructor(name) => write!(f, "{name}"),
CallType::EnumConstructor(name) => write!(f, "{name}"),
CallType::InstanceCreation(instance_creation_type) => match instance_creation_type {
InstanceCreationType::WitWorker { .. } => {
write!(f, "instance")
}
InstanceCreationType::WitResource { resource_name, .. } => {
write!(f, "{}", resource_name.resource_name)
}
},
}
}
}
#[cfg(feature = "protobuf")]
mod protobuf {
use crate::call_type::{CallType, InstanceCreationType};
use crate::FullyQualifiedResourceConstructor;
use crate::{ComponentDependencyKey, DynamicParsedFunctionName, Expr, ParsedFunctionName};
use golem_api_grpc::proto::golem::rib::WorkerInstance;
impl TryFrom<golem_api_grpc::proto::golem::rib::ComponentDependencyKey> for ComponentDependencyKey {
type Error = String;
fn try_from(
value: golem_api_grpc::proto::golem::rib::ComponentDependencyKey,
) -> Result<Self, Self::Error> {
let component_name = value.component_name;
let component_id = value.value.ok_or("Missing component id")?;
let component_version = value.component_version;
let root_package_name = value.root_package_name;
let root_package_version = value.root_package_version;
Ok(ComponentDependencyKey {
component_name,
component_id: component_id.into(),
component_version,
root_package_name,
root_package_version,
})
}
}
impl From<ComponentDependencyKey> for golem_api_grpc::proto::golem::rib::ComponentDependencyKey {
fn from(value: ComponentDependencyKey) -> Self {
golem_api_grpc::proto::golem::rib::ComponentDependencyKey {
component_name: value.component_name,
component_version: value.component_version,
value: Some(value.component_id.into()),
root_package_name: value.root_package_name,
root_package_version: value.root_package_version,
}
}
}
impl TryFrom<golem_api_grpc::proto::golem::rib::InstanceCreationType> for InstanceCreationType {
type Error = String;
fn try_from(
value: golem_api_grpc::proto::golem::rib::InstanceCreationType,
) -> Result<Self, Self::Error> {
match value.kind.ok_or("Missing instance creation kind")? {
golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Worker(
worker_instance,
) => {
let worker_name = worker_instance
.worker_name
.map(|w| Expr::try_from(*w))
.transpose()?
.map(Box::new);
Ok(InstanceCreationType::WitWorker {
component_info: None,
worker_name,
})
}
golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Resource(
resource_instance,
) => {
let resource_constructor_proto = resource_instance
.resource_name
.ok_or("Missing resource name")?;
let resource_name =
FullyQualifiedResourceConstructor::try_from(resource_constructor_proto)?;
let component_info = resource_instance
.component
.map(ComponentDependencyKey::try_from)
.transpose()?;
Ok(InstanceCreationType::WitResource {
component_info,
module: None,
resource_name,
})
}
}
}
}
impl From<InstanceCreationType> for golem_api_grpc::proto::golem::rib::InstanceCreationType {
fn from(value: InstanceCreationType) -> Self {
match value {
InstanceCreationType::WitWorker { component_info, .. } => {
golem_api_grpc::proto::golem::rib::InstanceCreationType {
kind: Some(golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Worker(Box::new(WorkerInstance {
component: component_info.map(golem_api_grpc::proto::golem::rib::ComponentDependencyKey::from),
worker_name: None
}))),
}
}
InstanceCreationType::WitResource { component_info, resource_name, .. } => {
golem_api_grpc::proto::golem::rib::InstanceCreationType {
kind: Some(golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Resource(Box::new(golem_api_grpc::proto::golem::rib::ResourceInstanceWithWorkerName {
component: component_info.map(golem_api_grpc::proto::golem::rib::ComponentDependencyKey::from),
worker_name: None,
resource_name: Some(golem_api_grpc::proto::golem::rib::FullyQualifiedResourceConstructor::from(resource_name)),
}))),
}
}
}
}
}
impl TryFrom<golem_api_grpc::proto::golem::rib::CallType> for CallType {
type Error = String;
fn try_from(
value: golem_api_grpc::proto::golem::rib::CallType,
) -> Result<Self, Self::Error> {
let invocation = value.name.ok_or("Missing name of invocation")?;
match invocation {
golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => {
Ok(CallType::Function {
component_info: None,
function_name: DynamicParsedFunctionName::try_from(name)?,
instance_identifier: None,
})
}
golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(name) => {
Ok(CallType::VariantConstructor(name))
}
golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(name) => {
Ok(CallType::EnumConstructor(name))
}
golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(
instance_creation,
) => {
let instance_creation = InstanceCreationType::try_from(*instance_creation)?;
Ok(CallType::InstanceCreation(instance_creation))
}
}
}
}
impl From<CallType> for golem_api_grpc::proto::golem::rib::CallType {
fn from(value: CallType) -> Self {
match value {
CallType::Function {
function_name,
..
} => golem_api_grpc::proto::golem::rib::CallType {
name: Some(golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(
function_name.into(),
)),
},
CallType::VariantConstructor(name) => golem_api_grpc::proto::golem::rib::CallType {
name: Some(
golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(
name,
),
),
},
CallType::EnumConstructor(name) => golem_api_grpc::proto::golem::rib::CallType {
name: Some(
golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(name),
),
},
CallType::InstanceCreation(instance_creation) => {
match instance_creation {
InstanceCreationType::WitWorker { worker_name , component_info} => {
golem_api_grpc::proto::golem::rib::CallType {
name: Some(golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(
Box::new(golem_api_grpc::proto::golem::rib::InstanceCreationType {
kind: Some(golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Worker(Box::new(WorkerInstance {
component: component_info.map(golem_api_grpc::proto::golem::rib::ComponentDependencyKey::from),
worker_name: worker_name.map(|w| Box::new(golem_api_grpc::proto::golem::rib::Expr::from(*w))),
}))),
})
)),
}
}
InstanceCreationType::WitResource { resource_name, component_info, .. } => {
golem_api_grpc::proto::golem::rib::CallType {
name: Some(golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(
Box::new(golem_api_grpc::proto::golem::rib::InstanceCreationType {
kind: Some(golem_api_grpc::proto::golem::rib::instance_creation_type::Kind::Resource(Box::new(golem_api_grpc::proto::golem::rib::ResourceInstanceWithWorkerName {
component: component_info.map(golem_api_grpc::proto::golem::rib::ComponentDependencyKey::from),
worker_name: None,
resource_name: Some(golem_api_grpc::proto::golem::rib::FullyQualifiedResourceConstructor::from(resource_name)),
}))),
})
)),
}
}
}
}
}
}
}
impl TryFrom<golem_api_grpc::proto::golem::rib::InvocationName> for CallType {
type Error = String;
fn try_from(
value: golem_api_grpc::proto::golem::rib::InvocationName,
) -> Result<Self, Self::Error> {
let invocation = value.name.ok_or("Missing name of invocation")?;
match invocation {
golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => {
Ok(CallType::Function {
component_info: None,
instance_identifier: None,
function_name: DynamicParsedFunctionName::parse(
ParsedFunctionName::try_from(name)?.to_string(),
)?,
})
}
golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(
name,
) => Ok(CallType::VariantConstructor(name)),
golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(name) => {
Ok(CallType::EnumConstructor(name))
}
}
}
}
}