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

Add --derive-for-type to cli #708

Merged
merged 4 commits into from
Nov 23, 2022
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
42 changes: 31 additions & 11 deletions cli/src/commands/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,38 +28,52 @@ pub struct Opts {
/// Additional derives
#[clap(long = "derive")]
derives: Vec<String>,
/// Additional derives for a given type.
///
/// Example `--derive-for-type my_module::my_type=serde::Serialize`.
#[clap(long = "derive-for-type", value_parser = derive_for_type_parser)]
derives_for_type: Vec<(String, String)>,
/// The `subxt` crate access path in the generated code.
/// Defaults to `::subxt`.
#[clap(long = "crate")]
crate_path: Option<String>,
}

fn derive_for_type_parser(src: &str) -> Result<(String, String), String> {
let (ty, derive) = src
.split_once('=')
.ok_or_else(|| String::from("Invalid pattern for `derive-for-type`. It should be `type=derive`, like `my_type=serde::Serialize`"))?;

Ok((ty.to_string(), derive.to_string()))
}

pub async fn run(opts: Opts) -> color_eyre::Result<()> {
if let Some(file) = opts.file.as_ref() {
let bytes = if let Some(file) = opts.file.as_ref() {
if opts.url.is_some() {
eyre::bail!("specify one of `--url` or `--file` but not both")
};

let mut file = fs::File::open(file)?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)?;
codegen(&bytes, opts.derives, opts.crate_path)?;
return Ok(())
}
bytes
} else {
let url = opts.url.unwrap_or_else(|| {
"http://localhost:9933"
.parse::<Uri>()
.expect("default url is valid")
});
subxt_codegen::utils::fetch_metadata_bytes(&url).await?
};

let url = opts.url.unwrap_or_else(|| {
"http://localhost:9933"
.parse::<Uri>()
.expect("default url is valid")
});
let bytes = subxt_codegen::utils::fetch_metadata_bytes(&url).await?;
codegen(&bytes, opts.derives, opts.crate_path)?;
codegen(&bytes, opts.derives, opts.derives_for_type, opts.crate_path)?;
Ok(())
}

fn codegen(
metadata_bytes: &[u8],
raw_derives: Vec<String>,
derives_for_type: Vec<(String, String)>,
crate_path: Option<String>,
) -> color_eyre::Result<()> {
let item_mod = syn::parse_quote!(
Expand All @@ -75,6 +89,12 @@ fn codegen(
let mut derives = DerivesRegistry::new(&crate_path);
derives.extend_for_all(p.into_iter());

for (ty, derive) in derives_for_type.into_iter() {
let ty = syn::parse_str(&ty)?;
let derive = syn::parse_str(&derive)?;
derives.extend_for_type(ty, std::iter::once(derive), &crate_path)
}

let runtime_api = subxt_codegen::generate_runtime_api_from_bytes(
item_mod,
metadata_bytes,
Expand Down
2 changes: 1 addition & 1 deletion examples/examples/storage_iterating.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

println!("\nExample 1. Obtained keys:");
while let Some((key, value)) = iter.next().await? {
println!("Key: 0x{}", hex::encode(&key));
println!("Key: 0x{}", hex::encode(key));
println!(" Value: {}", value);
}
}
Expand Down
2 changes: 1 addition & 1 deletion macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream {
let path = root_path.join(rest_of_path);
subxt_codegen::generate_runtime_api_from_path(
item_mod,
&path,
path,
derives_registry,
crate_path,
)
Expand Down
1 change: 0 additions & 1 deletion subxt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@

#![deny(
bad_style,
const_err,
niklasad1 marked this conversation as resolved.
Show resolved Hide resolved
improper_ctypes,
missing_docs,
non_shorthand_field_patterns,
Expand Down
4 changes: 2 additions & 2 deletions testing/test-runtime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async fn run() {
// Save metadata to a file:
let out_dir = env::var_os("OUT_DIR").unwrap();
let metadata_path = Path::new(&out_dir).join("metadata.scale");
fs::write(&metadata_path, &metadata_bytes.0).expect("Couldn't write metadata output");
fs::write(&metadata_path, metadata_bytes.0).expect("Couldn't write metadata output");

// Write out our expression to generate the runtime API to a file. Ideally, we'd just write this code
// in lib.rs, but we must pass a string literal (and not `concat!(..)`) as an arg to `runtime_metadata_path`,
Expand All @@ -101,7 +101,7 @@ async fn run() {
.expect("Path to metadata should be stringifiable")
);
let runtime_path = Path::new(&out_dir).join("runtime.rs");
fs::write(&runtime_path, runtime_api_contents)
fs::write(runtime_path, runtime_api_contents)
.expect("Couldn't write runtime rust output");

let substrate_path =
Expand Down
8 changes: 4 additions & 4 deletions testing/ui-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ fn ui_tests() {
let t = trybuild::TestCases::new();

// Check that storage maps with no keys are handled properly.
t.pass(&m.path_to_ui_test_for_metadata(
t.pass(m.path_to_ui_test_for_metadata(
"storage_map_no_keys",
storage::metadata_storage_map_no_keys(),
));

// Test that the codegen can handle the different types of DispatchError.
t.pass(&m.path_to_ui_test_for_metadata(
t.pass(m.path_to_ui_test_for_metadata(
"named_field_dispatch_error",
dispatch_errors::metadata_named_field_dispatch_error(),
));
t.pass(&m.path_to_ui_test_for_metadata(
t.pass(m.path_to_ui_test_for_metadata(
"legacy_dispatch_error",
dispatch_errors::metadata_legacy_dispatch_error(),
));
t.pass(&m.path_to_ui_test_for_metadata(
t.pass(m.path_to_ui_test_for_metadata(
"array_dispatch_error",
dispatch_errors::metadata_array_dispatch_error(),
));
Expand Down
4 changes: 2 additions & 2 deletions testing/ui-tests/src/utils/metadata_test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ impl MetadataTestRunner {

std::fs::create_dir_all(&tmp_dir).expect("could not create tmp ui test dir");
// Write metadata to tmp folder:
std::fs::write(&tmp_metadata_path, &encoded_metadata).unwrap();
std::fs::write(&tmp_metadata_path, encoded_metadata).unwrap();
// Write test file to tmp folder (it'll be moved by trybuild):
std::fs::write(&tmp_rust_path, &rust_file).unwrap();
std::fs::write(&tmp_rust_path, rust_file).unwrap();

tmp_rust_path
}
Expand Down