#![crate_type = "proc-macro"]
use proc_macro::TokenStream;
use proc_macro_error::proc_macro_error;
use quote::TokenStreamExt;
use syn::parse::Parse;
use syn::parse::ParseStream;
use syn::parse::Result;
use syn::punctuated::Punctuated;
mod entry_def_registration;
mod entry_defs;
mod entry_defs_conversions;
mod entry_defs_name_registration;
mod entry_helper;
mod entry_zomes;
mod link_types;
mod link_zomes;
mod to_coordinates;
mod unit_enum;
mod util;
struct EntryDef(holochain_integrity_types::entry_def::EntryDef);
struct EntryDefId(holochain_integrity_types::entry_def::EntryDefId);
struct EntryVisibility(holochain_integrity_types::entry_def::EntryVisibility);
struct RequiredValidations(holochain_integrity_types::entry_def::RequiredValidations);
struct RequiredValidationType(holochain_integrity_types::validate::RequiredValidationType);
impl Parse for EntryDef {
fn parse(input: ParseStream) -> Result<Self> {
let mut id =
holochain_integrity_types::entry_def::EntryDefId::App(String::default().into());
let mut required_validations =
holochain_integrity_types::entry_def::RequiredValidations::default();
let mut visibility = holochain_integrity_types::entry_def::EntryVisibility::default();
let vars = Punctuated::<syn::MetaNameValue, syn::Token![,]>::parse_terminated(input)?;
for var in vars {
if let Some(segment) = var.path.segments.first() {
match segment.ident.to_string().as_str() {
"id" => match var.lit {
syn::Lit::Str(s) => {
id = holochain_integrity_types::entry_def::EntryDefId::App(
s.value().to_string().into(),
)
}
_ => unreachable!(),
},
"required_validations" => match var.lit {
syn::Lit::Int(i) => {
required_validations =
holochain_integrity_types::entry_def::RequiredValidations::from(
i.base10_parse::<u8>()?,
)
}
_ => unreachable!(),
},
"visibility" => {
match var.lit {
syn::Lit::Str(s) => visibility = match s.value().as_str() {
"public" => {
holochain_integrity_types::entry_def::EntryVisibility::Public
}
"private" => {
holochain_integrity_types::entry_def::EntryVisibility::Private
}
_ => unreachable!(),
},
_ => unreachable!(),
};
}
_ => {}
}
}
}
Ok(EntryDef(holochain_integrity_types::entry_def::EntryDef {
id,
visibility,
required_validations,
cache_at_agent_activity: false,
}))
}
}
impl quote::ToTokens for EntryDefId {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match &self.0 {
holochain_integrity_types::entry_def::EntryDefId::App(s) => {
let string: String = s.0.to_string();
tokens.append_all(quote::quote! {
hdi::prelude::EntryDefId::App(#string.into())
});
}
_ => unreachable!(),
}
}
}
impl quote::ToTokens for RequiredValidations {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let u = <u8>::from(self.0);
tokens.append_all(quote::quote! {
hdi::prelude::RequiredValidations::from(#u)
});
}
}
impl quote::ToTokens for EntryVisibility {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let variant = syn::Ident::new(
match self.0 {
holochain_integrity_types::entry_def::EntryVisibility::Public => "Public",
holochain_integrity_types::entry_def::EntryVisibility::Private => "Private",
},
proc_macro2::Span::call_site(),
);
tokens.append_all(quote::quote! {
hdi::prelude::EntryVisibility::#variant
});
}
}
impl quote::ToTokens for RequiredValidationType {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let variant = syn::Ident::new(
match self.0 {
holochain_integrity_types::validate::RequiredValidationType::Record => "Record",
holochain_integrity_types::validate::RequiredValidationType::SubChain => "SubChain",
holochain_integrity_types::validate::RequiredValidationType::Full => "Full",
},
proc_macro2::Span::call_site(),
);
tokens.append_all(quote::quote! {
hdi::prelude::RequiredValidationType::#variant
});
}
}
impl quote::ToTokens for EntryDef {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let id = EntryDefId(self.0.id.clone());
let visibility = EntryVisibility(self.0.visibility);
let required_validations = RequiredValidations(self.0.required_validations);
tokens.append_all(quote::quote! {
hdi::prelude::EntryDef {
id: #id,
visibility: #visibility,
required_validations: #required_validations,
}
});
}
}
#[proc_macro_attribute]
pub fn hdk_extern(attrs: TokenStream, item: TokenStream) -> TokenStream {
let item_fn = syn::parse_macro_input!(item as syn::ItemFn);
let external_fn_ident = item_fn.sig.ident.clone();
let input_type = if let Some(syn::FnArg::Typed(pat_type)) = item_fn.sig.inputs.first() {
pat_type.ty.clone()
} else {
panic!("hdk_extern functions must take a single parameter");
};
let output_type = if let syn::ReturnType::Type(_, ref ty) = item_fn.sig.output {
ty.clone()
} else {
Box::new(syn::Type::Verbatim(quote::quote! { () }))
};
let internal_fn_ident = external_fn_ident.clone();
if attrs.to_string() == "infallible" {
(quote::quote! {
map_extern_infallible!(#external_fn_ident, #internal_fn_ident, #input_type, #output_type);
#item_fn
})
.into()
} else {
(quote::quote! {
map_extern!(#external_fn_ident, #internal_fn_ident, #input_type, #output_type);
#item_fn
})
.into()
}
}
#[proc_macro_error]
#[proc_macro_derive(EntryDefRegistration, attributes(entry_def))]
pub fn derive_entry_def_registration(input: TokenStream) -> TokenStream {
entry_def_registration::derive(input)
}
#[proc_macro_error]
#[proc_macro_derive(UnitEnum, attributes(unit_enum, unit_attrs))]
pub fn derive_to_unit_enum(input: TokenStream) -> TokenStream {
unit_enum::derive(input)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_entry_defs(attrs: TokenStream, code: TokenStream) -> TokenStream {
entry_defs::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_link_types(attrs: TokenStream, code: TokenStream) -> TokenStream {
link_types::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_to_coordinates(attrs: TokenStream, code: TokenStream) -> TokenStream {
to_coordinates::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_entry_defs_name_registration(attrs: TokenStream, code: TokenStream) -> TokenStream {
entry_defs_name_registration::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_entry_defs_conversions(attrs: TokenStream, code: TokenStream) -> TokenStream {
entry_defs_conversions::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_dependent_entry_types(attrs: TokenStream, code: TokenStream) -> TokenStream {
entry_zomes::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_dependent_link_types(attrs: TokenStream, code: TokenStream) -> TokenStream {
link_zomes::build(attrs, code)
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn hdk_entry_helper(attrs: TokenStream, code: TokenStream) -> TokenStream {
entry_helper::build(attrs, code)
}