use crate::renderer::data_renderer::full::quote_contract_struct::{
quote_contract_id_struct_name, quote_contract_struct_and_impl,
};
use crate::renderer::data_renderer::full::quote_interface::{quote_interface_choices, quote_interface_trait_path};
use crate::renderer::data_renderer::full::{quote_choice, quote_daml_record_and_impl};
use crate::renderer::{RenderContext, quote_escaped_ident, to_module_path};
use daml_lf::element::DamlTemplate;
use proc_macro2::TokenStream;
use quote::quote;
pub fn quote_daml_template(ctx: &RenderContext<'_>, daml_template: &DamlTemplate<'_>) -> TokenStream {
let struct_and_impl_tokens = quote_daml_record_and_impl(ctx, daml_template.name(), daml_template.fields(), &[]);
let template_id_method_tokens = quote_template_id_method(
daml_template.name(),
ctx.package_name_for(daml_template.package_id()),
daml_template.package_id(),
to_module_path(daml_template.module_path()),
);
let make_create_method_tokens = quote_make_create_command_method(daml_template.name());
let contract_struct_and_impl_tokens = quote_contract_struct_and_impl(daml_template.name());
let choices_impl_tokens = quote_choice(ctx, daml_template.name(), daml_template.choices());
let interface_impls_tokens = quote_interface_impls(daml_template);
let interface_choice_tokens = quote_implemented_interface_choices(ctx, daml_template);
quote!(
#struct_and_impl_tokens
#template_id_method_tokens
#make_create_method_tokens
#contract_struct_and_impl_tokens
#choices_impl_tokens
#interface_impls_tokens
#interface_choice_tokens
)
}
fn quote_implemented_interface_choices(ctx: &RenderContext<'_>, daml_template: &DamlTemplate<'_>) -> TokenStream {
let blocks: Vec<_> = daml_template
.implements()
.iter()
.filter_map(|iface_name| ctx.archive().interface_by_tycon_name(iface_name))
.map(|iface| quote_interface_choices(ctx, daml_template.name(), iface))
.collect();
quote!(#( #blocks )*)
}
fn quote_interface_impls(daml_template: &DamlTemplate<'_>) -> TokenStream {
let contract_id_struct_name_tokens = quote_contract_id_struct_name(daml_template.name());
let impls: Vec<_> = daml_template
.implements()
.iter()
.map(|iface| {
let trait_path = quote_interface_trait_path(iface);
quote!(impl #trait_path for #contract_id_struct_name_tokens {})
})
.collect();
quote!(#( #impls )*)
}
pub fn quote_template_id_method(
struct_name: &str,
package_name: Option<&str>,
package_id: &str,
module_name: String,
) -> TokenStream {
let struct_name_tokens = quote_escaped_ident(struct_name);
let entity_name = struct_name;
let identifier_ctor = if let Some(name) = package_name {
quote!(DamlIdentifier::from_package_name(#name, #module_name, #entity_name))
} else {
quote!(DamlIdentifier::new(#package_id, #module_name, #entity_name))
};
quote!(
impl #struct_name_tokens {
pub fn template_id() -> DamlIdentifier {
#identifier_ctor
}
}
)
}
pub fn quote_make_create_command_method(struct_name: &str) -> TokenStream {
let struct_name_tokens = quote_escaped_ident(struct_name);
quote!(
impl #struct_name_tokens {
pub fn create_command(&self) -> DamlCreateCommand {
let template_id = Self::template_id();
let value: DamlValue = self.to_owned().serialize_into();
DamlCreateCommand::new(
template_id,
value.try_take_record().expect("serialize_into always produces a Record"),
)
}
}
)
}