Skip to content

Commit 5402c89

Browse files
authored
chore: improve stripping file prefixes (foundry-rs#164)
Use utils to avoid allocations, add stripping methods to ArtifactId for foundry-rs/foundry#8294
1 parent 2353967 commit 5402c89

File tree

12 files changed

+68
-59
lines changed

12 files changed

+68
-59
lines changed

crates/artifacts/solc/src/bytecode.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,7 @@ where
384384
{
385385
match bytecode {
386386
BytecodeObject::Bytecode(code) => s.serialize_str(&hex::encode(code)),
387-
BytecodeObject::Unlinked(code) => {
388-
s.serialize_str(code.strip_prefix("0x").unwrap_or(code.as_str()))
389-
}
387+
BytecodeObject::Unlinked(code) => s.serialize_str(code.strip_prefix("0x").unwrap_or(code)),
390388
}
391389
}
392390

crates/artifacts/solc/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ use crate::output_selection::{ContractOutputSelection, OutputSelection};
3838
use foundry_compilers_core::{
3939
error::SolcError,
4040
utils::{
41-
BERLIN_SOLC, BYZANTIUM_SOLC, CANCUN_SOLC, CONSTANTINOPLE_SOLC, ISTANBUL_SOLC, LONDON_SOLC,
42-
PARIS_SOLC, PETERSBURG_SOLC, SHANGHAI_SOLC,
41+
strip_prefix_owned, BERLIN_SOLC, BYZANTIUM_SOLC, CANCUN_SOLC, CONSTANTINOPLE_SOLC,
42+
ISTANBUL_SOLC, LONDON_SOLC, PARIS_SOLC, PETERSBURG_SOLC, SHANGHAI_SOLC,
4343
},
4444
};
4545
pub use serde_helpers::{deserialize_bytes, deserialize_opt_bytes};
@@ -167,7 +167,7 @@ impl SolcInput {
167167
pub fn strip_prefix(&mut self, base: &Path) {
168168
self.sources = std::mem::take(&mut self.sources)
169169
.into_iter()
170-
.map(|(path, s)| (path.strip_prefix(base).map(Into::into).unwrap_or(path), s))
170+
.map(|(path, s)| (strip_prefix_owned(path, base), s))
171171
.collect();
172172

173173
self.settings.strip_prefix(base);
@@ -505,7 +505,7 @@ impl Settings {
505505
(
506506
Path::new(&file)
507507
.strip_prefix(base)
508-
.map(|p| format!("{}", p.display()))
508+
.map(|p| p.display().to_string())
509509
.unwrap_or(file),
510510
selection,
511511
)
@@ -521,7 +521,7 @@ impl Settings {
521521
(
522522
Path::new(&path)
523523
.strip_prefix(base)
524-
.map(|p| format!("{}", p.display()))
524+
.map(|p| p.display().to_string())
525525
.unwrap_or(path),
526526
contracts,
527527
)

crates/artifacts/solc/src/remappings.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl Remapping {
6868
/// Removes the `base` path from the remapping
6969
pub fn strip_prefix(&mut self, base: &Path) -> &mut Self {
7070
if let Ok(stripped) = Path::new(&self.path).strip_prefix(base) {
71-
self.path = format!("{}", stripped.display());
71+
self.path = stripped.display().to_string();
7272
}
7373
self
7474
}
@@ -356,7 +356,7 @@ impl fmt::Display for RelativeRemapping {
356356
impl From<RelativeRemapping> for Remapping {
357357
fn from(r: RelativeRemapping) -> Self {
358358
let RelativeRemapping { context, mut name, path } = r;
359-
let mut path = format!("{}", path.relative().display());
359+
let mut path = path.relative().display().to_string();
360360
if !path.ends_with('/') {
361361
path.push('/');
362362
}

crates/artifacts/vyper/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ workspace = true
1616

1717
[dependencies]
1818
foundry-compilers-artifacts-solc.workspace = true
19+
foundry-compilers-core.workspace = true
1920

2021
serde.workspace = true
2122
alloy-primitives.workspace = true

crates/artifacts/vyper/src/input.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use std::path::Path;
2-
31
use super::VyperSettings;
42
use foundry_compilers_artifacts_solc::sources::Sources;
3+
use foundry_compilers_core::utils::strip_prefix_owned;
54
use serde::{Deserialize, Serialize};
5+
use std::path::Path;
66

77
/// Extension of Vyper interface file.
88
pub const VYPER_INTERFACE_EXTENSION: &str = "vyi";
@@ -37,12 +37,12 @@ impl VyperInput {
3737
pub fn strip_prefix(&mut self, base: &Path) {
3838
self.sources = std::mem::take(&mut self.sources)
3939
.into_iter()
40-
.map(|(path, s)| (path.strip_prefix(base).map(Into::into).unwrap_or(path), s))
40+
.map(|(path, s)| (strip_prefix_owned(path, base), s))
4141
.collect();
4242

4343
self.interfaces = std::mem::take(&mut self.interfaces)
4444
.into_iter()
45-
.map(|(path, s)| (path.strip_prefix(base).map(Into::into).unwrap_or(path), s))
45+
.map(|(path, s)| (strip_prefix_owned(path, base), s))
4646
.collect();
4747

4848
self.settings.strip_prefix(base)

crates/artifacts/vyper/src/settings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl VyperSettings {
4444
(
4545
Path::new(&file)
4646
.strip_prefix(base)
47-
.map(|p| format!("{}", p.display()))
47+
.map(|p| p.display().to_string())
4848
.unwrap_or(file),
4949
selection,
5050
)

crates/compilers/src/artifact_output/mod.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use foundry_compilers_artifacts::{
1010
};
1111
use foundry_compilers_core::{
1212
error::{Result, SolcError, SolcIoError},
13-
utils,
13+
utils::{self, strip_prefix_owned},
1414
};
1515
use path_slash::PathBufExt;
1616
use semver::Version;
@@ -70,6 +70,19 @@ impl ArtifactId {
7070
self
7171
}
7272

73+
/// Removes `base` from the source's path.
74+
pub fn strip_file_prefixes(&mut self, base: &Path) {
75+
if let Ok(stripped) = self.source.strip_prefix(base) {
76+
self.source = stripped.to_path_buf();
77+
}
78+
}
79+
80+
/// Convenience function for [`Self::strip_file_prefixes()`]
81+
pub fn with_stripped_file_prefixes(mut self, base: &Path) -> Self {
82+
self.strip_file_prefixes(base);
83+
self
84+
}
85+
7386
/// Returns a `<filename>:<name>` slug that identifies an artifact
7487
///
7588
/// Note: This identifier is not necessarily unique. If two contracts have the same name, they
@@ -125,8 +138,8 @@ impl<T> ArtifactFile<T> {
125138

126139
/// Removes `base` from the artifact's path
127140
pub fn strip_prefix(&mut self, base: &Path) {
128-
if let Ok(prefix) = self.file.strip_prefix(base) {
129-
self.file = prefix.to_path_buf();
141+
if let Ok(stripped) = self.file.strip_prefix(base) {
142+
self.file = stripped.to_path_buf();
130143
}
131144
}
132145
}
@@ -352,19 +365,8 @@ impl<T> Artifacts<T> {
352365
/// Strips the given prefix from all artifact file paths to make them relative to the given
353366
/// `root` argument
354367
pub fn into_stripped_file_prefixes(self, base: &Path) -> Self {
355-
let artifacts = self
356-
.0
357-
.into_iter()
358-
.map(|(file, c)| {
359-
let file_path = Path::new(&file);
360-
if let Ok(p) = file_path.strip_prefix(base) {
361-
(p.to_path_buf(), c)
362-
} else {
363-
(file, c)
364-
}
365-
})
366-
.collect();
367-
368+
let artifacts =
369+
self.0.into_iter().map(|(path, c)| (strip_prefix_owned(path, base), c)).collect();
368370
Self(artifacts)
369371
}
370372

crates/compilers/src/cache.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use foundry_compilers_artifacts::{
1414
};
1515
use foundry_compilers_core::{
1616
error::{Result, SolcError},
17-
utils,
17+
utils::{self, strip_prefix},
1818
};
1919
use semver::Version;
2020
use serde::{de::DeserializeOwned, Deserialize, Serialize};
@@ -619,14 +619,14 @@ impl<'a, T: ArtifactOutput, C: Compiler> ArtifactsCacheInner<'a, T, C> {
619619
.edges
620620
.imports(&file)
621621
.into_iter()
622-
.map(|import| utils::source_name(import, self.project.root()).to_path_buf())
622+
.map(|import| strip_prefix(import, self.project.root()).into())
623623
.collect();
624624

625625
let entry = CacheEntry {
626626
last_modification_date: CacheEntry::<C::Settings>::read_last_modification_date(&file)
627627
.unwrap_or_default(),
628628
content_hash: source.content_hash(),
629-
source_name: utils::source_name(&file, self.project.root()).into(),
629+
source_name: strip_prefix(&file, self.project.root()).into(),
630630
compiler_settings: self.project.settings.clone(),
631631
imports,
632632
version_requirement: self.edges.version_requirement(&file).map(|v| v.to_string()),

crates/compilers/src/compile/output/sources.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::SourceFile;
2+
use foundry_compilers_core::utils::strip_prefix_owned;
23
use semver::Version;
34
use serde::{Deserialize, Serialize};
45
use std::{
@@ -194,9 +195,7 @@ impl VersionedSourceFiles {
194195
pub fn strip_prefix_all(&mut self, base: &Path) -> &mut Self {
195196
self.0 = std::mem::take(&mut self.0)
196197
.into_iter()
197-
.map(|(file_path, sources)| {
198-
(file_path.strip_prefix(base).unwrap_or(&file_path).to_path_buf(), sources)
199-
})
198+
.map(|(file, sources)| (strip_prefix_owned(file, base), sources))
200199
.collect();
201200
self
202201
}

crates/compilers/src/config.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use foundry_compilers_artifacts::{
1313
};
1414
use foundry_compilers_core::{
1515
error::{Result, SolcError, SolcIoError},
16-
utils,
16+
utils::{self, strip_prefix_owned},
1717
};
1818
use serde::{Deserialize, Serialize};
1919
use std::{
@@ -661,27 +661,25 @@ impl ProjectPaths {
661661

662662
/// Removes `base` from all folders
663663
pub fn strip_prefix_all(&mut self, base: &Path) -> &mut Self {
664-
if let Ok(prefix) = self.artifacts.strip_prefix(base) {
665-
self.artifacts = prefix.to_path_buf();
664+
if let Ok(stripped) = self.artifacts.strip_prefix(base) {
665+
self.artifacts = stripped.to_path_buf();
666666
}
667-
if let Ok(prefix) = self.build_infos.strip_prefix(base) {
668-
self.build_infos = prefix.to_path_buf();
667+
if let Ok(stripped) = self.build_infos.strip_prefix(base) {
668+
self.build_infos = stripped.to_path_buf();
669669
}
670-
if let Ok(prefix) = self.sources.strip_prefix(base) {
671-
self.sources = prefix.to_path_buf();
670+
if let Ok(stripped) = self.sources.strip_prefix(base) {
671+
self.sources = stripped.to_path_buf();
672672
}
673-
if let Ok(prefix) = self.tests.strip_prefix(base) {
674-
self.tests = prefix.to_path_buf();
673+
if let Ok(stripped) = self.tests.strip_prefix(base) {
674+
self.tests = stripped.to_path_buf();
675675
}
676-
if let Ok(prefix) = self.scripts.strip_prefix(base) {
677-
self.scripts = prefix.to_path_buf();
676+
if let Ok(stripped) = self.scripts.strip_prefix(base) {
677+
self.scripts = stripped.to_path_buf();
678678
}
679-
let libraries = std::mem::take(&mut self.libraries);
680-
self.libraries.extend(
681-
libraries
682-
.into_iter()
683-
.map(|p| p.strip_prefix(base).map(|p| p.to_path_buf()).unwrap_or(p)),
684-
);
679+
self.libraries = std::mem::take(&mut self.libraries)
680+
.into_iter()
681+
.map(|path| strip_prefix_owned(path, base))
682+
.collect();
685683
self
686684
}
687685
}

crates/compilers/src/filter.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,13 @@ impl<'a> SparseOutputFilter<'a> {
156156

157157
// set output selections
158158
for file in sources.0.keys() {
159-
let key = format!("{}", file.display());
160-
if full_compilation.contains(file) {
161-
selection.as_mut().insert(key, default_selection.clone());
159+
let key = file.display().to_string();
160+
let output = if full_compilation.contains(file) {
161+
default_selection.clone()
162162
} else {
163-
selection.as_mut().insert(key, OutputSelection::empty_file_output_select());
164-
}
163+
OutputSelection::empty_file_output_select()
164+
};
165+
selection.as_mut().insert(key, output);
165166
}
166167
});
167168

crates/core/src/utils.rs

+10
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,19 @@ pub fn solidity_dirs(root: &Path) -> Vec<PathBuf> {
210210
///
211211
/// `/Users/project/sources/contract.sol` -> `sources/contracts.sol`
212212
pub fn source_name<'a>(source: &'a Path, root: &Path) -> &'a Path {
213+
strip_prefix(source, root)
214+
}
215+
216+
/// Strips `root` from `source` and returns the relative path.
217+
pub fn strip_prefix<'a>(source: &'a Path, root: &Path) -> &'a Path {
213218
source.strip_prefix(root).unwrap_or(source)
214219
}
215220

221+
/// Strips `root` from `source` and returns the relative path.
222+
pub fn strip_prefix_owned(source: PathBuf, root: &Path) -> PathBuf {
223+
source.strip_prefix(root).map(Path::to_path_buf).unwrap_or(source)
224+
}
225+
216226
/// Attempts to determine if the given source is a local, relative import.
217227
pub fn is_local_source_name(libs: &[impl AsRef<Path>], source: impl AsRef<Path>) -> bool {
218228
resolve_library(libs, source.as_ref()).is_none()

0 commit comments

Comments
 (0)