subweight_core/parse/
mod.rs

1//! Parses weight files of Substrate chains.
2//!
3//! The following categories are supported:
4//! - Extrinsic weights (often pallet_name.rs)
5//! - Database weights (often rocksdb_weights.rs or paritydb_weights.rs)
6//! - Extrinsic Base weight (often extrinsic_weight.rs)
7//! - Block Execution weight (often block_weight.rs)
8//!
9//! Each module corresponds to one of these categories.
10
11pub mod overhead;
12pub mod pallet;
13pub mod storage;
14
15use std::{io::Read, path::Path};
16
17pub enum ParsedFile {
18	Pallet(Vec<pallet::ChromaticExtrinsic>),
19	Storage(storage::Weights),
20	Overhead(overhead::Weight),
21}
22
23/// Defines how a path is transformed into a pallet name.
24///
25/// Take the following example:
26///
27///  Compare `old/pallet.rs` to `new/pallet.rs`.
28///  Obviously the pallet should have the same name in both cases.
29///  The solution is to only look at the file name.
30///
31/// Next example:
32///
33///  Compare `polkadot/pallet.rs` to `polkadot/template/pallet.rs`.
34///  It this case the pallet name is different, since it are two distinct runtimes.
35///  The pallets should not be compared to each other but registered as `Added`.
36#[derive(Copy, clap::ValueEnum, PartialEq, Eq, Clone, Debug)]
37pub enum PathStripping {
38	/// Only the file name.
39	FileName,
40	/// The path relative to the repository.
41	RepoRelative,
42}
43
44impl PathStripping {
45	pub fn strip(&self, repo: &Path, path: &Path) -> String {
46		match self {
47			Self::FileName => path.file_name().unwrap().to_string_lossy(),
48			Self::RepoRelative => path.strip_prefix(repo).unwrap_or(path).to_string_lossy(),
49		}
50		.into_owned()
51	}
52
53	pub fn variants() -> Vec<&'static str> {
54		vec!["file_name", "repo_relative"]
55	}
56}
57
58impl std::str::FromStr for PathStripping {
59	type Err = String;
60
61	fn from_str(s: &str) -> Result<Self, String> {
62		match s {
63			"file_name" => Ok(Self::FileName),
64			"repo_relative" => Ok(Self::RepoRelative),
65			_ => Err(format!("Unknown stripping: {}", s)),
66		}
67	}
68}
69
70/// Tries to guess the type of weight file and parses it.
71///
72/// Does not return an error since it just *tires* to do so, not guarantee.
73pub fn try_parse_file(repo: &Path, file: &Path) -> Option<ParsedFile> {
74	if let Ok(parsed) = pallet::parse_file_in_repo(repo, file) {
75		return Some(ParsedFile::Pallet(parsed))
76	}
77	if let Ok(parsed) = storage::parse_file(file) {
78		return Some(ParsedFile::Storage(parsed))
79	}
80	if let Ok(parsed) = overhead::parse_file(file) {
81		return Some(ParsedFile::Overhead(parsed))
82	}
83
84	None
85}
86
87pub fn read_file(file: &Path) -> Result<String, String> {
88	let mut raw = std::fs::File::options()
89		.read(true)
90		.write(false)
91		.open(file)
92		.map_err(|e| format!("{}: {:?}", file.display(), e))?;
93	let mut content = String::new();
94	raw.read_to_string(&mut content)
95		.map_err(|e| format!("{}: {:?}", file.display(), e))?;
96	Ok(content)
97}
98
99pub(crate) fn path_to_string(p: &syn::Path, delimiter: Option<&str>) -> String {
100	p.segments
101		.iter()
102		.map(|s| s.ident.to_string())
103		.collect::<Vec<_>>()
104		.join(delimiter.unwrap_or_default())
105}