Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feat(solc): add Contract Info structs #1407

Merged
merged 1 commit into from
Jun 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
2 changes: 1 addition & 1 deletion ethers-solc/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{
};
pub mod many;
pub mod output;
pub use output::{contracts, sources};
pub use output::{contracts, info, sources};
pub mod project;

/// The name of the `solc` binary on the system
Expand Down
118 changes: 118 additions & 0 deletions ethers-solc/src/compile/output/info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//! Commonly used identifiers for contracts in the compiled output
use std::{convert::TryFrom, fmt, str::FromStr};

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{0}")]
pub struct ParseContractInfoError(String);

/// Represents the common contract argument pattern for `<path>:<contractname>` where `<path>:` is
/// optional.
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ContractInfo {
/// Location of the contract
pub path: Option<String>,
/// Name of the contract
pub name: String,
}

// === impl ContractInfo ===

impl ContractInfo {
/// Creates a new `ContractInfo` from the `info` str.
///
/// This will attempt `ContractInfo::from_str`, if `info` matches the `<path>:<name>` format,
/// the `ContractInfo`'s `path` will be set.
///
/// otherwise the `name` of the new object will be `info`.
///
/// # Example
///
/// ```
/// use ethers_solc::info::ContractInfo;
/// let info = ContractInfo::new("src/Greeter.sol:Greeter");
/// assert_eq!(info, ContractInfo {path: Some("src/Greeter.sol".to_string()), name: "Greeter".to_string()});
/// ```
pub fn new(info: impl AsRef<str>) -> Self {
let info = info.as_ref();
info.parse().unwrap_or_else(|_| ContractInfo { path: None, name: info.to_string() })
}
}

impl fmt::Display for ContractInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(ref path) = self.path {
write!(f, "{}:{}", path, self.name)
} else {
write!(f, "{}", self.name)
}
}
}

impl FromStr for ContractInfo {
type Err = ParseContractInfoError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let err = || {
ParseContractInfoError(
"contract source info format must be `<path>:<contractname>` or `<contractname>`"
.to_string(),
)
};
let mut iter = s.rsplit(':');
let name = iter.next().ok_or_else(err)?.trim().to_string();
let path = iter.next().map(str::to_string);

if name.ends_with(".sol") || name.contains('/') {
return Err(err())
}

Ok(Self { path, name })
}
}

impl From<FullContractInfo> for ContractInfo {
fn from(info: FullContractInfo) -> Self {
let FullContractInfo { path, name } = info;
ContractInfo { path: Some(path), name }
}
}

/// Represents the common contract argument pattern `<path>:<contractname>`
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct FullContractInfo {
/// Location of the contract
pub path: String,
/// Name of the contract
pub name: String,
}

impl fmt::Display for FullContractInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.path, self.name)
}
}

impl FromStr for FullContractInfo {
type Err = ParseContractInfoError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let (path, name) = s.split_once(':').ok_or_else(|| {
ParseContractInfoError("Expected `<path>:<contractname>`, got `{s}`".to_string())
})?;
Ok(Self { path: path.to_string(), name: name.trim().to_string() })
}
}

impl TryFrom<ContractInfo> for FullContractInfo {
type Error = ParseContractInfoError;

fn try_from(value: ContractInfo) -> Result<Self, Self::Error> {
let ContractInfo { path, name } = value;
Ok(FullContractInfo {
path: path.ok_or_else(|| {
ParseContractInfoError("path to contract must be present".to_string())
})?,
name,
})
}
}
1 change: 1 addition & 0 deletions ethers-solc/src/compile/output/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::{collections::BTreeMap, fmt, path::Path};
use tracing::trace;

pub mod contracts;
pub mod info;
pub mod sources;

/// Contains a mixture of already compiled/cached artifacts and the input set of sources that still
Expand Down