perf(solc): wrap source content in Arc (#2138)

This commit is contained in:
Matthias Seitz 2023-02-11 01:17:11 +01:00 committed by GitHub
parent bfe3ba9d5f
commit c7547cb1d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 12 deletions

View File

@ -18,7 +18,7 @@ keywords = ["ethereum", "web3", "solc", "solidity", "ethers"]
[dependencies]
ethers-core = { version = "^1.0.0", path = "../ethers-core", default-features = false }
serde_json = "1.0.68"
serde = { version = "1.0.130", features = ["derive"] }
serde = { version = "1.0.130", features = ["derive", "rc"] }
semver = { version = "1.0.16", features = ["serde"] }
walkdir = "2.3.2"
tokio = { version = "1.18", default-features = false, features = ["rt"] }

View File

@ -11,6 +11,7 @@ use std::{
fmt, fs,
path::{Path, PathBuf},
str::FromStr,
sync::Arc,
};
use tracing::warn;
use yansi::Paint;
@ -1195,16 +1196,29 @@ pub struct DocLibraries {
pub libs: BTreeMap<String, serde_json::Value>,
}
/// Content of a solidity file
///
/// This contains the actual source code of a file
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Source {
pub content: String,
/// Content of the file
///
/// This is an `Arc` because it may be cloned. If the [Graph](crate::resolver::Graph) of the
/// project contains multiple conflicting versions then the same [Source] may be required by
/// conflicting versions and needs to be duplicated.
pub content: Arc<String>,
}
impl Source {
/// Reads the file content
/// Creates a new instance of [Source] with the given content.
pub fn new(content: impl Into<String>) -> Self {
Self { content: Arc::new(content.into()) }
}
/// Reads the file's content
pub fn read(file: impl AsRef<Path>) -> Result<Self, SolcIoError> {
let file = file.as_ref();
Ok(Self { content: fs::read_to_string(file).map_err(|err| SolcIoError::new(err, file))? })
Ok(Self::new(fs::read_to_string(file).map_err(|err| SolcIoError::new(err, file))?))
}
/// Recursively finds all source files under the given dir path and reads them all
@ -1254,7 +1268,7 @@ impl Source {
/// Generate a non-cryptographically secure checksum of the file's content
pub fn content_hash(&self) -> String {
let mut hasher = md5::Md5::new();
hasher.update(&self.content);
hasher.update(self);
let result = hasher.finalize();
hex::encode(result)
}
@ -1270,11 +1284,9 @@ impl Source {
/// async version of `Self::read`
pub async fn async_read(file: impl AsRef<Path>) -> Result<Self, SolcIoError> {
let file = file.as_ref();
Ok(Self {
content: tokio::fs::read_to_string(file)
.await
.map_err(|err| SolcIoError::new(err, file))?,
})
Ok(Self::new(
tokio::fs::read_to_string(file).await.map_err(|err| SolcIoError::new(err, file))?,
))
}
/// Finds all source files under the given dir path and reads them all
@ -1306,6 +1318,12 @@ impl AsRef<str> for Source {
}
}
impl AsRef<[u8]> for Source {
fn as_ref(&self) -> &[u8] {
self.content.as_bytes()
}
}
/// Output type `solc` produces
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)]
pub struct CompilerOutput {

View File

@ -104,7 +104,7 @@ mod tests {
fn build_info_serde() {
let inputs = CompilerInput::with_sources(BTreeMap::from([(
PathBuf::from("input.sol"),
Source { content: "".to_string() },
Source::new(""),
)]));
let output = CompilerOutput::default();
let v: Version = "0.8.4+commit.c7e474f2".parse().unwrap();

View File

@ -909,6 +909,6 @@ mod tests {
///// helpers
fn source(version: &str) -> Source {
Source { content: format!("pragma solidity {version};\n") }
Source::new(format!("pragma solidity {version};\n"))
}
}