Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: add custom derives from user #46

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions contracts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ generate_artifacts:
jq .abi ${scarb_build}simple_interface${sierra} > ${artifacts}simple_interface.abi.json
jq .abi ${scarb_build}structs${sierra} > ${artifacts}structs.abi.json
jq .abi ${scarb_build}byte_array${sierra} > ${artifacts}byte_array.abi.json
jq .abi ${scarb_build}gen${sierra} > ${artifacts}gen.abi.json

generate_rust:
scarb build
Expand Down Expand Up @@ -50,11 +51,14 @@ setup_byte_array:
# starkli declare target/dev/contracts_basic.sierra.json ${config}
# starkli deploy ${class_hash} --salt 0x1234 ${config}

# # Declare and deploy the basic contract on katana.
# setup_gen:
# $(eval class_hash=$(shell starkli class-hash target/dev/contracts_gen.sierra.json))
# starkli declare target/dev/contracts_gen.sierra.json ${config}
# starkli deploy ${class_hash} --salt 0x1234 ${config}
# Declare and deploy the basic contract on katana.
setup_gen:
@set -x; \
scarb build; \
class_hash=$$(starkli class-hash ${scarb_build}gen${sierra}); \
starkli declare ${scarb_build}gen${sierra} ${config}; \
sleep 2; \
starkli deploy "$${class_hash}" --salt 0x1234 ${config}

# # Declare and deploy the event contract on katana.
# setup_event:
Expand Down
1 change: 1 addition & 0 deletions contracts/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ mod abicov {

mod simple_get_set;
mod basic;
mod gen;
2 changes: 2 additions & 0 deletions crates/rs-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn abigen_internal(input: TokenStream) -> TokenStream {
&contract_name.to_string(),
&abi_tokens,
contract_abi.execution_version,
&contract_abi.derives,
);

if let Some(out_path) = contract_abi.output_path {
Expand Down Expand Up @@ -61,6 +62,7 @@ fn abigen_internal_legacy(input: TokenStream) -> TokenStream {
&contract_name.to_string(),
&abi_tokens,
cainome_rs::ExecutionVersion::V1,
&[],
);

if let Some(out_path) = contract_abi.output_path {
Expand Down
12 changes: 12 additions & 0 deletions crates/rs-macro/src/macro_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub(crate) struct ContractAbi {
pub output_path: Option<String>,
pub type_aliases: HashMap<String, String>,
pub execution_version: ExecutionVersion,
pub derives: Vec<String>,
}

impl Parse for ContractAbi {
Expand Down Expand Up @@ -89,6 +90,7 @@ impl Parse for ContractAbi {
let mut output_path: Option<String> = None;
let mut execution_version = ExecutionVersion::V1;
let mut type_aliases = HashMap::new();
let mut derives = Vec::new();

loop {
if input.parse::<Token![,]>().is_err() {
Expand Down Expand Up @@ -135,6 +137,15 @@ impl Parse for ContractAbi {
syn::Error::new(content.span(), format!("Invalid execution version: {}", e))
})?;
}
"derives" => {
let content;
parenthesized!(content in input);
let parsed = content.parse_terminated(Spanned::<Type>::parse, Token![,])?;

for derive in parsed {
derives.push(derive.to_token_stream().to_string());
}
}
_ => panic!("unexpected named parameter `{}`", name),
}
}
Expand All @@ -145,6 +156,7 @@ impl Parse for ContractAbi {
output_path,
type_aliases,
execution_version,
derives,
})
}
}
Expand Down
15 changes: 9 additions & 6 deletions crates/rs/src/expand/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::expand::utils;
pub struct CairoEnum;

impl CairoEnum {
pub fn expand_decl(composite: &Composite) -> TokenStream2 {
pub fn expand_decl(composite: &Composite, derives: &[String]) -> TokenStream2 {
if composite.is_builtin() {
return quote!();
}
Expand All @@ -29,6 +29,12 @@ impl CairoEnum {
}
}

let mut internal_derives = vec![];

for d in derives {
internal_derives.push(utils::str_to_type(d));
}

if composite.is_generic() {
let gen_args: Vec<Ident> = composite
.generic_args
Expand All @@ -42,18 +48,15 @@ impl CairoEnum {
// Add one phantom for each generic type.
// Those phantom fields are ignored by serde.

// TODO: as for struct, we need to have a better way for the user to specify the
// traits to derive.

quote! {
#[derive(Debug, PartialEq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
#[derive(#(#internal_derives,)*)]
pub enum #enum_name<#(#gen_args),*> {
#(#variants),*
}
}
} else {
quote! {
#[derive(Debug, PartialEq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
#[derive(#(#internal_derives,)*)]
pub enum #enum_name {
#(#variants),*
}
Expand Down
15 changes: 9 additions & 6 deletions crates/rs/src/expand/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::expand::utils;
pub struct CairoStruct;

impl CairoStruct {
pub fn expand_decl(composite: &Composite) -> TokenStream2 {
pub fn expand_decl(composite: &Composite, derives: &[String]) -> TokenStream2 {
if composite.is_builtin() {
return quote!();
}
Expand All @@ -35,6 +35,12 @@ impl CairoStruct {
}
}

let mut internal_derives = vec![];

for d in derives {
internal_derives.push(utils::str_to_type(d));
}

if composite.is_generic() {
let gen_args: Vec<Ident> = composite
.generic_args
Expand All @@ -48,18 +54,15 @@ impl CairoStruct {
// Add one phantom for each generic type.
// Those phantom fields are ignored by serde.

// TODO: add a way for the user to specify which trait must be derived for the
// generated structs. For now Serde is used to ensure easy serialization.

quote! {
#[derive(Debug, PartialEq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
#[derive(#(#internal_derives,)*)]
pub struct #struct_name<#(#gen_args),*> {
#(pub #members),*
}
}
} else {
quote! {
#[derive(Debug, PartialEq, PartialOrd, Clone, serde::Serialize, serde::Deserialize)]
#[derive(#(#internal_derives,)*)]
pub struct #struct_name {
#(pub #members),*
}
Expand Down
16 changes: 12 additions & 4 deletions crates/rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub struct Abigen {
pub types_aliases: HashMap<String, String>,
/// The version of transaction to be executed.
pub execution_version: ExecutionVersion,
/// Derives to be added to the generated types.
pub derives: Vec<String>,
}

impl Abigen {
Expand All @@ -83,6 +85,7 @@ impl Abigen {
abi_source: Utf8PathBuf::from(abi_source),
types_aliases: HashMap::new(),
execution_version: ExecutionVersion::V1,
derives: vec![],
}
}

Expand Down Expand Up @@ -112,8 +115,12 @@ impl Abigen {

match AbiParser::tokens_from_abi_string(&file_content, &self.types_aliases) {
Ok(tokens) => {
let expanded =
abi_to_tokenstream(&self.contract_name, &tokens, self.execution_version);
let expanded = abi_to_tokenstream(
&self.contract_name,
&tokens,
self.execution_version,
&self.derives,
);

Ok(ContractBindings {
name: self.contract_name.clone(),
Expand All @@ -140,6 +147,7 @@ pub fn abi_to_tokenstream(
contract_name: &str,
abi_tokens: &TokenizedAbi,
execution_version: ExecutionVersion,
derives: &[String],
) -> TokenStream2 {
let contract_name = utils::str_to_ident(contract_name);

Expand All @@ -149,13 +157,13 @@ pub fn abi_to_tokenstream(

for s in &abi_tokens.structs {
let s_composite = s.to_composite().expect("composite expected");
tokens.push(CairoStruct::expand_decl(s_composite));
tokens.push(CairoStruct::expand_decl(s_composite, derives));
tokens.push(CairoStruct::expand_impl(s_composite));
}

for e in &abi_tokens.enums {
let e_composite = e.to_composite().expect("composite expected");
tokens.push(CairoEnum::expand_decl(e_composite));
tokens.push(CairoEnum::expand_decl(e_composite, derives));
tokens.push(CairoEnum::expand_impl(e_composite));

tokens.push(CairoEnumEvent::expand(
Expand Down
22 changes: 22 additions & 0 deletions examples/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use cainome::rs::abigen;

use starknet::core::types::Felt;

abigen!(
MyContract,
"./contracts/abi/gen.abi.json",
derives(Debug, Clone)
);

#[tokio::main]
async fn main() {
let s = MyStruct::<Felt> {
f1: Felt::ONE,
f2: Felt::TWO,
f3: Felt::THREE,
};

println!("{:?}", s);

let _s2 = s.clone();
}
5 changes: 5 additions & 0 deletions src/bin/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ pub struct CainomeArgs {
#[arg(value_name = "EXECUTION_VERSION")]
#[arg(help = "The execution version to use. Supported values are 'v1', 'V1', 'v3', or 'V3'.")]
pub execution_version: ExecutionVersion,

#[arg(long)]
#[arg(value_name = "DERIVES")]
#[arg(help = "Derives to be added to the generated types.")]
pub derives: Option<Vec<String>>,
}

#[derive(Debug, Args, Clone)]
Expand Down
1 change: 1 addition & 0 deletions src/bin/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ async fn main() -> CainomeCliResult<()> {
output_dir: args.output_dir,
contracts,
execution_version: args.execution_version,
derives: args.derives.unwrap_or_default(),
})
.await?;

Expand Down
1 change: 1 addition & 0 deletions src/bin/cli/plugins/builtins/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl BuiltinPlugin for RustPlugin {
&contract_name,
&contract.tokens,
input.execution_version,
&input.derives,
);
let filename = format!(
"{}.rs",
Expand Down
1 change: 1 addition & 0 deletions src/bin/cli/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct PluginInput {
pub output_dir: Utf8PathBuf,
pub contracts: Vec<ContractData>,
pub execution_version: ExecutionVersion,
pub derives: Vec<String>,
}

#[derive(Debug)]
Expand Down
Loading